diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionEnhancement.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionEnhancement.java new file mode 100644 index 0000000000..2b8be32f3f --- /dev/null +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionEnhancement.java @@ -0,0 +1,282 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.ads.googleads.examples.remarketing; + +import com.beust.jcommander.Parameter; +import com.google.ads.googleads.examples.utils.ArgumentNames; +import com.google.ads.googleads.examples.utils.CodeSampleParams; +import com.google.ads.googleads.lib.GoogleAdsClient; +import com.google.ads.googleads.v8.common.OfflineUserAddressInfo; +import com.google.ads.googleads.v8.common.UserIdentifier; +import com.google.ads.googleads.v8.enums.ConversionAdjustmentTypeEnum.ConversionAdjustmentType; +import com.google.ads.googleads.v8.enums.UserIdentifierSourceEnum.UserIdentifierSource; +import com.google.ads.googleads.v8.errors.GoogleAdsError; +import com.google.ads.googleads.v8.errors.GoogleAdsException; +import com.google.ads.googleads.v8.services.ConversionAdjustment; +import com.google.ads.googleads.v8.services.ConversionAdjustmentResult; +import com.google.ads.googleads.v8.services.ConversionAdjustmentUploadServiceClient; +import com.google.ads.googleads.v8.services.RestatementValue; +import com.google.ads.googleads.v8.services.UploadConversionAdjustmentsRequest; +import com.google.ads.googleads.v8.services.UploadConversionAdjustmentsResponse; +import com.google.ads.googleads.v8.utils.ResourceNames; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * Adjusts an existing conversion by supplying user identifiers so Google can enhance the conversion + * value. + */ +public class UploadConversionEnhancement { + private static class UploadConversionEnhancementParams extends CodeSampleParams { + + @Parameter(names = ArgumentNames.CUSTOMER_ID, required = true) + private long customerId; + + @Parameter(names = ArgumentNames.CONVERSION_ACTION_ID, required = true) + private long conversionActionId; + + @Parameter(names = ArgumentNames.ORDER_ID, required = true) + private String orderId; + + @Parameter(names = ArgumentNames.USER_AGENT, required = false) + private String userAgent; + + @Parameter(names = ArgumentNames.RESTATEMENT_VALUE, required = false) + private Double restatementValue; + + @Parameter( + names = ArgumentNames.CURRENCY_CODE, + required = false, + description = "The currency of the restatement value.") + private String currencyCode; + } + + public static void main(String[] args) + throws UnsupportedEncodingException, NoSuchAlgorithmException { + UploadConversionEnhancementParams params = new UploadConversionEnhancementParams(); + if (!params.parseArguments(args)) { + + // Either pass the required parameters for this example on the command line, or insert them + // into the code here. See the parameter class definition above for descriptions. + params.customerId = Long.parseLong("INSERT_CUSTOMER_ID_HERE"); + params.conversionActionId = Long.parseLong("INSERT_CONVERSION_ACTION_ID_HERE"); + params.orderId = "INSERT_ORDER_ID_HERE"; + + // Optional: Specify the user agent, restatement value and restatement currency code. + params.userAgent = null; + params.restatementValue = null; + params.currencyCode = null; + } + + GoogleAdsClient googleAdsClient = null; + try { + googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build(); + } catch (FileNotFoundException fnfe) { + System.err.printf( + "Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe); + System.exit(1); + } catch (IOException ioe) { + System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe); + System.exit(1); + } + + try { + new UploadConversionEnhancement() + .runExample( + googleAdsClient, + params.customerId, + params.conversionActionId, + params.orderId, + params.userAgent, + params.restatementValue, + params.currencyCode); + } catch (GoogleAdsException gae) { + // GoogleAdsException is the base class for most exceptions thrown by an API request. + // Instances of this exception have a message and a GoogleAdsFailure that contains a + // collection of GoogleAdsErrors that indicate the underlying causes of the + // GoogleAdsException. + System.err.printf( + "Request ID %s failed due to GoogleAdsException. Underlying errors:%n", + gae.getRequestId()); + int i = 0; + for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) { + System.err.printf(" Error %d: %s%n", i++, googleAdsError); + } + System.exit(1); + } + } + + /** + * Runs the example. + * + * @param googleAdsClient the Google Ads API client. + * @param customerId the client customer ID. + * @param conversionActionId conversion action ID associated with this conversion. + * @param orderId unique order ID (transaction ID) of the conversion. + * @param userAgent the HTTP user agent of the conversion. + * @param restatementValue the enhancement value. + * @param restatementCurrencyCode the currency of the enhancement value. + */ + // [START upload_conversion_enhancement] + private void runExample( + GoogleAdsClient googleAdsClient, + long customerId, + long conversionActionId, + String orderId, + String userAgent, + Double restatementValue, + String restatementCurrencyCode) + throws NoSuchAlgorithmException, UnsupportedEncodingException { + // [START create_adjustment] + // Creates a builder for constructing the enhancement adjustment. + ConversionAdjustment.Builder enhancementBuilder = + ConversionAdjustment.newBuilder() + .setConversionAction(ResourceNames.conversionAction(customerId, conversionActionId)) + .setAdjustmentType(ConversionAdjustmentType.ENHANCEMENT) + // Enhancements MUST use order ID instead of GCLID date/time pair. + .setOrderId(orderId); + + // 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"); + + // Adds user identifiers, hashing where required. + + // Creates a user identifier using sample values for the user address. + UserIdentifier addressIdentifier = + UserIdentifier.newBuilder() + // User identifiers for conversion enhancements MUST use first party data. + .setUserIdentifierSource(UserIdentifierSource.FIRST_PARTY) + .setAddressInfo( + OfflineUserAddressInfo.newBuilder() + .setHashedFirstName(normalizeAndHash(sha256Digest, "Joanna")) + .setHashedLastName(normalizeAndHash(sha256Digest, "Smith")) + .setHashedStreetAddress( + normalizeAndHash(sha256Digest, "1600 Amphitheatre Pkwy")) + .setCity("Mountain View") + .setState("CA") + .setPostalCode("94043") + .setCountryCode("US")) + .build(); + + // Creates a user identifier using the hashed email address. + UserIdentifier emailIdentifier = + UserIdentifier.newBuilder() + .setUserIdentifierSource(UserIdentifierSource.FIRST_PARTY) + // Uses the normalize and hash method specifically for email addresses. + .setHashedEmail(normalizeAndHashEmailAddress(sha256Digest, "joannasmith@example.com")) + .build(); + + // Adds the user identifiers to the enhancement adjustment. + enhancementBuilder.addUserIdentifiers(addressIdentifier).addUserIdentifiers(emailIdentifier); + + // Sets optional fields where a value was provided. + + if (userAgent != null) { + // Sets the user agent. This should match the user agent of the request that sent the original + // conversion so the conversion and its enhancement are either both attributed as same-device + // or both attributed as cross-device. + enhancementBuilder.setUserAgent(userAgent); + } + + if (restatementValue != null) { + // Creates a builder to construct the restated conversion value. + RestatementValue.Builder valueBuilder = enhancementBuilder.getRestatementValueBuilder(); + // Sets the new value of the conversion. + valueBuilder.setAdjustedValue(restatementValue); + // Sets the currency of the new value, if provided. Otherwise, the default currency from + // the conversion action is used, and if that is not set then the account currency is used. + if (restatementCurrencyCode != null) { + valueBuilder.setCurrencyCode(restatementCurrencyCode); + } + } + // [END create_adjustment] + + // Creates the conversion upload service client. + try (ConversionAdjustmentUploadServiceClient conversionUploadServiceClient = + googleAdsClient.getLatestVersion().createConversionAdjustmentUploadServiceClient()) { + // Uploads the enhancement adjustment. Partial failure should always be set to true. + UploadConversionAdjustmentsResponse response = + conversionUploadServiceClient.uploadConversionAdjustments( + UploadConversionAdjustmentsRequest.newBuilder() + .setCustomerId(Long.toString(customerId)) + .addConversionAdjustments(enhancementBuilder) + // Enables partial failure (must be true). + .setPartialFailure(true) + .build()); + + // Prints any partial errors returned. + if (response.hasPartialFailureError()) { + System.out.printf( + "Partial error encountered: '%s'.%n", response.getPartialFailureError().getMessage()); + } else { + // Prints the result. + ConversionAdjustmentResult result = response.getResults(0); + System.out.printf( + "Uploaded conversion adjustment of '%s' for order ID '%s'.%n", + result.getConversionAction(), result.getOrderId()); + } + } + } + // [END upload_conversion_enhancement] + + /** + * 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. + * + * @param digest the digest to use to hash the normalized string. + * @param s the string to normalize and hash. + */ + // [START normalize_and_hash] + 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, 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); + } + // [END normalize_and_hash] +} diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionWithIdentifiers.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionWithIdentifiers.java new file mode 100644 index 0000000000..1792d8718d --- /dev/null +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionWithIdentifiers.java @@ -0,0 +1,256 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.ads.googleads.examples.remarketing; + +import com.beust.jcommander.Parameter; +import com.google.ads.googleads.examples.utils.ArgumentNames; +import com.google.ads.googleads.examples.utils.CodeSampleParams; +import com.google.ads.googleads.lib.GoogleAdsClient; +import com.google.ads.googleads.v8.common.UserIdentifier; +import com.google.ads.googleads.v8.enums.UserIdentifierSourceEnum.UserIdentifierSource; +import com.google.ads.googleads.v8.errors.GoogleAdsError; +import com.google.ads.googleads.v8.errors.GoogleAdsException; +import com.google.ads.googleads.v8.services.ClickConversion; +import com.google.ads.googleads.v8.services.ClickConversionResult; +import com.google.ads.googleads.v8.services.ConversionUploadServiceClient; +import com.google.ads.googleads.v8.services.UploadClickConversionsRequest; +import com.google.ads.googleads.v8.services.UploadClickConversionsResponse; +import com.google.ads.googleads.v8.utils.ResourceNames; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** Uploads a conversion using hashed email address instead of GCLID. */ +public class UploadConversionWithIdentifiers { + private static class UploadConversionWithIdentifiersParams extends CodeSampleParams { + + @Parameter(names = ArgumentNames.CUSTOMER_ID, required = true) + private long customerId; + + @Parameter(names = ArgumentNames.CONVERSION_ACTION_ID, required = true) + private long conversionActionId; + + @Parameter(names = ArgumentNames.EMAIL_ADDRESS, required = true) + private String emailAddress; + + @Parameter( + names = ArgumentNames.CONVERSION_DATE_TIME, + required = true, + description = + "The date time at which the conversion occurred. " + + "Must be after the click time, and must include the time zone offset. " + + "The format is 'yyyy-mm-dd hh:mm:ss+|-hh:mm', e.g. '2019-01-01 12:32:45-08:00'.") + private String conversionDateTime; + + @Parameter(names = ArgumentNames.CONVERSION_VALUE, required = true) + private Double conversionValue; + + @Parameter(names = ArgumentNames.ORDER_ID, required = false) + private String orderId; + } + + public static void main(String[] args) + throws UnsupportedEncodingException, NoSuchAlgorithmException { + UploadConversionWithIdentifiersParams params = new UploadConversionWithIdentifiersParams(); + if (!params.parseArguments(args)) { + + // Either pass the required parameters for this example on the command line, or insert them + // into the code here. See the parameter class definition above for descriptions. + params.customerId = Long.parseLong("INSERT_CUSTOMER_ID_HERE"); + params.conversionActionId = Long.parseLong("INSERT_CONVERSION_ACTION_ID_HERE"); + params.emailAddress = "INSERT_EMAIL_ADDRESS_HERE"; + params.conversionDateTime = "INSERT_CONVERSION_DATE_TIME_HERE"; + params.conversionValue = Double.parseDouble("INSERT_CONVERSION_VALUE_HERE"); + // Optional: Specify the unique order ID for the click conversion. + params.orderId = null; + } + + GoogleAdsClient googleAdsClient = null; + try { + googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build(); + } catch (FileNotFoundException fnfe) { + System.err.printf( + "Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe); + System.exit(1); + } catch (IOException ioe) { + System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe); + System.exit(1); + } + + try { + new UploadConversionWithIdentifiers() + .runExample( + googleAdsClient, + params.customerId, + params.conversionActionId, + params.emailAddress, + params.conversionDateTime, + params.conversionValue, + params.orderId); + } catch (GoogleAdsException gae) { + // GoogleAdsException is the base class for most exceptions thrown by an API request. + // Instances of this exception have a message and a GoogleAdsFailure that contains a + // collection of GoogleAdsErrors that indicate the underlying causes of the + // GoogleAdsException. + System.err.printf( + "Request ID %s failed due to GoogleAdsException. Underlying errors:%n", + gae.getRequestId()); + int i = 0; + for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) { + System.err.printf(" Error %d: %s%n", i++, googleAdsError); + } + System.exit(1); + } + } + + /** + * Runs the example. + * + * @param googleAdsClient the Google Ads API client. + * @param customerId the client customer ID. + * @param conversionActionId conversion action ID associated with this conversion. + * @param emailAddress email address for the conversion. + * @param conversionDateTime date and time of the conversion. + * @param conversionValue the value of the conversion. + * @param orderId the unique ID (transaction ID) of the conversion. + */ + // [START upload_conversion_with_identifiers] + private void runExample( + GoogleAdsClient googleAdsClient, + long customerId, + long conversionActionId, + String emailAddress, + String conversionDateTime, + Double conversionValue, + String orderId) + throws UnsupportedEncodingException, NoSuchAlgorithmException { + // [START create_conversion] + // Gets the conversion action resource name. + String conversionActionResourceName = + ResourceNames.conversionAction(customerId, conversionActionId); + + // Creates a builder for constructing the click conversion. + ClickConversion.Builder clickConversionBuilder = + ClickConversion.newBuilder() + .setConversionAction(conversionActionResourceName) + .setConversionDateTime(conversionDateTime) + .setConversionValue(conversionValue) + .setCurrencyCode("USD"); + + // Sets the order ID if provided. + if (orderId != null) { + clickConversionBuilder.setOrderId(orderId); + } + + // 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 user identifier using the hashed email address, using the normalize and hash method + // specifically for email addresses. + // If using a phone number, use the normalizeAndHash(String) method instead. + String hashedEmail = normalizeAndHashEmailAddress(sha256Digest, emailAddress); + UserIdentifier userIdentifier = + UserIdentifier.newBuilder() + // User identifiers for conversion enhancements MUST use first party data. + .setUserIdentifierSource(UserIdentifierSource.FIRST_PARTY) + .setHashedEmail(hashedEmail) + .build(); + + // Adds the user identifier to the conversion. + clickConversionBuilder.addUserIdentifiers(userIdentifier); + + // Calls build to build the conversion. + ClickConversion clickConversion = clickConversionBuilder.build(); + // [END create_conversion] + + // Creates the conversion upload service client. + try (ConversionUploadServiceClient conversionUploadServiceClient = + googleAdsClient.getLatestVersion().createConversionUploadServiceClient()) { + // Uploads the click conversion. Partial failure should always be set to true. + UploadClickConversionsResponse response = + conversionUploadServiceClient.uploadClickConversions( + UploadClickConversionsRequest.newBuilder() + .setCustomerId(Long.toString(customerId)) + .addConversions(clickConversion) + // Enables partial failure (must be true). + .setPartialFailure(true) + .build()); + + // Prints any partial errors returned. + if (response.hasPartialFailureError()) { + System.out.printf( + "Partial error encountered: '%s'.%n", response.getPartialFailureError().getMessage()); + } + + // Prints the result. + ClickConversionResult result = response.getResults(0); + // Only prints valid results. + if (result.hasGclid()) { + System.out.printf( + "Uploaded conversion that occurred at '%s' from Google Click ID '%s' to '%s'.%n", + result.getConversionDateTime(), result.getGclid(), result.getConversionAction()); + } + } + } + // [END upload_conversion_with_identifiers] + + /** + * 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. + * + * @param digest the digest to use to hash the normalized string. + * @param s the string to normalize and hash. + */ + // [START normalize_and_hash] + 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, 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); + } + // [END normalize_and_hash] +} diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadOfflineConversion.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadOfflineConversion.java index 534da23b7f..5f4bd2eeae 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadOfflineConversion.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadOfflineConversion.java @@ -56,12 +56,16 @@ private static class UploadOfflineConversionParams extends CodeSampleParams { private Double conversionValue; // Optional: Specify the conversion custom variable ID and value you want to - // associate with the call conversion upload. + // associate with the click conversion upload. @Parameter(names = ArgumentNames.CONVERSION_CUSTOM_VARIABLE_ID) private Long conversionCustomVariableId; @Parameter(names = ArgumentNames.CONVERSION_CUSTOM_VARIABLE_VALUE) private String conversionCustomVariableValue; + + // Optional: Specify the unique order ID for the click conversion. + @Parameter(names = ArgumentNames.ORDER_ID) + private String orderId; } public static void main(String[] args) { @@ -76,9 +80,11 @@ public static void main(String[] args) { params.conversionDateTime = "INSERT_CONVERSION_DATE_TIME_HERE"; params.conversionValue = Double.parseDouble("INSERT_CONVERSION_VALUE_HERE"); // Optionally specify the conversion custom variable ID and value you want to - // associate with the call conversion upload. + // associate with the click conversion upload. params.conversionCustomVariableId = null; params.conversionCustomVariableValue = null; + // Optionally specify the order ID for the click conversion. + params.orderId = null; } GoogleAdsClient googleAdsClient = null; @@ -103,7 +109,8 @@ public static void main(String[] args) { params.conversionDateTime, params.conversionValue, params.conversionCustomVariableId, - params.conversionCustomVariableValue); + params.conversionCustomVariableValue, + params.orderId); } catch (GoogleAdsException gae) { // GoogleAdsException is the base class for most exceptions thrown by an API request. // Instances of this exception have a message and a GoogleAdsFailure that contains a @@ -133,6 +140,7 @@ public static void main(String[] args) { * the upload. * @param conversionCustomVariableValue the value of the conversion custom variable to associate * with the upload. + * @param orderId the unique ID (transaction ID) of the conversion. */ // [START upload_offline_conversion] private void runExample( @@ -143,7 +151,8 @@ private void runExample( String conversionDateTime, Double conversionValue, Long conversionCustomVariableId, - String conversionCustomVariableValue) { + String conversionCustomVariableValue, + String orderId) { // Gets the conversion action resource name. String conversionActionResourceName = ResourceNames.conversionAction(customerId, conversionActionId); @@ -158,6 +167,7 @@ private void runExample( .setGclid(gclid); if (conversionCustomVariableId != null && conversionCustomVariableValue != null) { + // Sets the custom variable and value, if provided. clickConversionBuilder.addCustomVariables( CustomVariable.newBuilder() .setConversionCustomVariable( @@ -165,6 +175,12 @@ private void runExample( .setValue(conversionCustomVariableValue)); } + if (orderId != null) { + // Sets the order ID (unique transaction ID), if provided. An order ID is required in order to + // upload enhancements as shown in the UploadConversionEnhancement example. + clickConversionBuilder.setOrderId(orderId); + } + ClickConversion clickConversion = clickConversionBuilder.build(); // Creates the conversion upload service client. diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/utils/ArgumentNames.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/utils/ArgumentNames.java index a2172bcc42..348794e2d8 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/utils/ArgumentNames.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/utils/ArgumentNames.java @@ -55,6 +55,7 @@ public final class ArgumentNames { public static final String CPC_BID_MICRO_AMOUNT = "--cpcBidMicroAmount"; public static final String CREATE_DEFAULT_LISTING_GROUP = "--createDefaultListingGroup"; public static final String CRITERION_ID = "--criterionId"; + public static final String CURRENCY_CODE = "--currencyCode"; public static final String CUSTOMER_ID = "--customerId"; public static final String CUSTOM_KEY = "--customKey"; public static final String CUSTOMER_IDS = "--customerIds"; @@ -89,6 +90,7 @@ public final class ArgumentNames { public static final String MARKETING_IMAGE_ASSET_ID = "--marketingImageAssetId"; public static final String MERCHANT_CENTER_ACCOUNT_ID = "--merchantCenterAccountId"; public static final String OFFLINE_USER_DATA_JOB_TYPE = "--offlineUserDataJobType"; + public static final String ORDER_ID = "--orderId"; public static final String PAGE_URL = "--pageUrl"; public static final String PARTNER_ID = "--partnerId"; public static final String PAYMENTS_ACCOUNT_ID_ID = "--paymentsAccountId"; @@ -101,6 +103,7 @@ public final class ArgumentNames { public static final String SITELINK_TEXT = "--sitelinkText"; public static final String SQUARE_MARKETING_IMAGE_ID = "--squareMarketingImageAssetId"; public static final String START_DATE_TIME = "--startDateTime"; + public static final String USER_AGENT = "--userAgent"; public static final String USER_LIST_ID = "--userListId"; public static final String USER_LIST_IDS = "--userListIds"; }