Register for one of our Google Ads API Migration Workshops (October 5, 2021 - October 14, 2021)

Upload with Form Data

In addition to uploading conversions by GCLID, the Google Ads API also supports uploading with user identifiers collected in form submissions such as lead forms.

To upload conversions using identifiers, follow the same process you would for uploading conversions by GCLID, but make the following changes when populating each ClickConversion:

  • Instead of setting gclid, populate the user_identifiers with the standardized and hashed email address or phone number of the user. If available, you may add both values in separate UserIdentifiers on the same ClickConversion.

  • Ensure that the user_identifier_source of each identifier is set to FIRST_PARTY.

  • Set the conversion_action to a resource name of a ConversionAction with a type of UPLOAD_CLICKS.

  • Do not set external_attribution_data or specify a conversion_action that uses an external attribution model. Google Ads does not support externally attributed conversions for uploads using identifiers.

Normalization and hashing

For privacy concerns, email addresses and phone numbers must be hashed using the SHA-256 algorithm before being uploaded. In order to standardize the hash results, prior to hashing one of these values you must:

  • Remove leading/trailing whitespaces.
  • Convert the text to lowercase.
  • Format phone numbers according to the E164 standard.
  • Remove all periods (.) that precede the domain name in gmail.com and googlemail.com email addresses.

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, 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);
}
      
      

C#

This example is not yet available in C#; you can take a look at the other languages.
    

PHP

This example is not yet available in PHP; you can take a look at the other languages.
    

Python

This example is not yet available in Python; you can take a look at the other languages.
    

Ruby

This example is not yet available in Ruby; you can take a look at the other languages.
    

Perl

This example is not yet available in Perl; you can take a look at the other languages.
    

Upload conversions code example

The following snippet demonstrates how to construct a conversion upload that contains an identifier for email address, with standardization and hashing applied as required.

Java

// 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();
      
      

C#

This example is not yet available in C#; you can take a look at the other languages.
    

PHP

This example is not yet available in PHP; you can take a look at the other languages.
    

Python

This example is not yet available in Python; you can take a look at the other languages.
    

Ruby

This example is not yet available in Ruby; you can take a look at the other languages.
    

Perl

This example is not yet available in Perl; you can take a look at the other languages.
    

Common errors

ConversionUploadError.CLICK_NOT_FOUND
No click was found that matched the provided user identifiers.
ConversionUploadError.INVALID_USER_IDENTIFIER
A user_identifier for a field that requires hashing was not hashed using the SHA-256 algorithm.
ConversionUploadError.EXTERNALLY_ATTRIBUTED_CONVERSION_ACTION_NOT_PERMITTED_WITH_USER_IDENTIFIER
The conversion_action specified uses an external attribution model.
ConversionUploadError.UNSUPPORTED_USER_IDENTIFIER
A user_identifier of the conversion contains a value that is not one of the allowed identifiers (hashed_email_address and hashed_phone_number).
CollectionSizeError.TOO_MANY
The user_identifiers collection contains more than five elements.