Share your feedback about the Google Ads (AdWords) API. Take the 2021 AdWords API and Google Ads API Annual Survey.

Enhanced Conversions

Using the Google Ads API, you can leverage enhanced conversions by sending first-party customer data in the form of conversion adjustments. Google uses this additional data to improve the reporting of your online conversions driven by ad interactions.

You must complete the setup and configuration steps before you can use enhanced conversions in the Google Ads API.

Overview

The process for sending data for enhanced conversions is similar to other conversion adjustments, but keep the following key differences in mind when populating the ConversionAdjustment:

  • order_id is required.
  • adjustment_type must be ENHANCEMENT.
  • conversion_action must be the resource_name of a ConversionAction with a type of WEBPAGE and enhanced conversions enabled.
  • user_identifiers must contain between one and five identifiers. Enhancements support the following identifiers:
    • hashed_email
    • hashed_phone_number
    • address_info
  • user_identifier_source of each identifier is optional.
  • user_agent is optional but recommended. 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.
  • restatement_value with adjusted_value and currency_code are optional but recommended.

In addition, you must upload the enhancement adjustment within 24 hours of the original conversion for the order_id. To avoid errors due to differences in clock times, upload the adjustment no later than several minutes before the end of the 24-hour period.

Normalization and hashing

For privacy concerns, email addresses, phone numbers, first names, last names, and street addresses 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.
    

Enhancement adjustments

The following snippet demonstrates how to construct an enhancement adjustment that contains identifiers for email address and user address, with standardization and hashing applied as required.

Java

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

// Sets the conversion date and time if provided. Providing this value is optional but
// recommended.
if (conversionDateTime != null) {
  enhancementBuilder.setGclidDateTimePair(
      GclidDateTimePair.newBuilder().setConversionDateTime(conversionDateTime));
}

// 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()
        .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"))
        // Optional: Specifies the user identifier source.
        .setUserIdentifierSource(UserIdentifierSource.FIRST_PARTY)
        .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);
  }
}
      

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

Use the enhanced conversions API diagnostics report to validate that your enhanced conversions are working effectively.

Here are some common errors that may occur during uploads:

ConversionAdjustmentUploadError.CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS
The customer data terms and conditions have not been accepted for the customer_id of the request.
ConversionAdjustmentUploadError.CONVERSION_ACTION_NOT_ELIGIBLE_FOR_ENHANCEMENT
The conversion_action supplied is not eligible for enhanced conversions. In the Google Ads UI, make sure you check the Turn on enhanced conversions box on the conversion action referenced in your request.
ConversionAdjustmentUploadError.INVALID_USER_IDENTIFIER
A user_identifier for a field that requires hashing was not hashed using the SHA-256 algorithm.
ConversionAdjustmentUploadError.UNSUPPORTED_USER_IDENTIFIER
A user_identifier of the adjustment contains a value that is not one of the allowed identifiers.
CollectionSizeError.TOO_MANY
The user_identifiers collection contains more than five elements.