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

Customer Match

You can find more information on Customer Match requirements and eligibility in the Google Ads Help Center.

Customer Match with email address, address, or user ID

For advertisers with rich CRM databases, you can define and target audience lists based on your CRM data. You can upload CRM data in bulk, append/remove data, or use these user lists to create a logical_user_list.

These audience lists are eligible to serve on Google Search, YouTube, Gmail, and the Google Display Network.

Per policy, you will only be allowed to upload data that you have acquired yourself (first party). You are not allowed to buy email lists from third parties and upload them into the account.

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

Java

// Creates the first user data based on an email address.
UserData userDataWithEmailAddress =
    UserData.newBuilder()
        .addUserIdentifiers(
            UserIdentifier.newBuilder()
                .setHashedEmail(normalizeAndHash(sha256Digest, "customer@example.com")))
        .build();

// Creates the second user data based on a physical address.
UserData userDataWithPhysicalAddress =
    UserData.newBuilder()
        .addUserIdentifiers(
            UserIdentifier.newBuilder()
                .setAddressInfo(
                    OfflineUserAddressInfo.newBuilder()
                        .setHashedFirstName(normalizeAndHash(sha256Digest, "John"))
                        .setHashedLastName(normalizeAndHash(sha256Digest, "Doe"))
                        .setCountryCode("US")
                        .setPostalCode("10011")))
        .build();
      
      

C#

// Creates a first user data based on an email address.
UserData userDataWithEmailAddress = new UserData()
{
    UserIdentifiers = {
        new UserIdentifier()
        {
            // Hash normalized email addresses based on SHA-256 hashing algorithm.
            HashedEmail = NormalizeAndHash("customer@example.com")
        }
    }
};

// Creates a second user data based on a physical address.
UserData userDataWithPhysicalAddress = new UserData()
{
    UserIdentifiers =
    {
        new UserIdentifier()
        {
            AddressInfo = new OfflineUserAddressInfo()
            {
                // First and last name must be normalized and hashed.
                HashedFirstName = NormalizeAndHash("John"),
                HashedLastName = NormalizeAndHash("Doe"),
                // Country code and zip code are sent in plain text.
                CountryCode = "US",
                PostalCode = "10011"
            }
        }
    }
};
      
      

PHP

// Creates a first user data based on an email address.
$userDataWithEmailAddress = new UserData([
    'user_identifiers' => [
        new UserIdentifier([
            // Hash normalized email addresses based on SHA-256 hashing algorithm.
            'hashed_email' => self::normalizeAndHash('customer@example.com')
        ])
    ]
]);

// Creates a second user data based on a physical address.
$userDataWithPhysicalAddress = new UserData([
    'user_identifiers' => [
        new UserIdentifier([
            'address_info' => new OfflineUserAddressInfo([
                // First and last name must be normalized and hashed.
                'hashed_first_name' => self::normalizeAndHash('John'),
                'hashed_last_name' => self::normalizeAndHash('Doe'),
                // Country code and zip code are sent in plain text.
                'country_code' => 'US',
                'postal_code' => '10011'
            ])
        ])
    ]
]);
      
      

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

# Create a first user data based on an email address.
my $user_data_with_email_address =
  Google::Ads::GoogleAds::V8::Common::UserData->new({
    userIdentifiers => [
      Google::Ads::GoogleAds::V8::Common::UserIdentifier->new({
          # Hash normalized email addresses based on SHA-256 hashing algorithm.
          hashedEmail => normalize_and_hash('customer@example.com')})]});

# Create a second user data based on a physical address.
my $user_data_with_physical_address =
  Google::Ads::GoogleAds::V8::Common::UserData->new({
    userIdentifiers => [
      Google::Ads::GoogleAds::V8::Common::UserIdentifier->new({
          addressInfo =>
            Google::Ads::GoogleAds::V8::Common::OfflineUserAddressInfo->new({
              # First and last name must be normalized and hashed.
              hashedFirstName => normalize_and_hash("John"),
              hashedLastName  => normalize_and_hash("Doe"),
              # Country code and zip code are sent in plain text.
              countryCode => "US",
              postalCode  => "10011"
            })})]});
      
      

Options for Customer Match in different campaign types

Search network only campaigns
A crm_based_user_list is available. Ads will show on the search network.
Display network only campaigns
A crm_based_user_list and its similar_user_list are available. Ads will show on Gmail only if there are GSP creatives.
Search network with display select campaigns
A crm_based_user_list is available. Ads will show on the search network and on Gmail (only if there are GSP creatives).
Video campaigns
A crm_based_user_list and its similar_user_list are available. Ads will show on YouTube only if there are in-stream TrueView ads.

Customer Match with phone number

Similar to Customer Match with emails, you can also perform customer matching with phone numbers.

For privacy concerns, the phone number needs to be hashed using the SHA-256 algorithm before being uploaded. In order to standardize results, convert each phone number to E164 format before hashing. This format represents a phone number as a number up to fifteen digits in length starting with a + sign (e.g. +12125650000, +442070313000).

If the phone number is not correctly formatted before hashing, the API will still accept the hashed phone number, but the phone number will not be matched with a customer.

Customer Match with mobile device IDs

Similar to Customer Match with emails, you can also perform customer matching using IDFA (Identifier for Advertising) or AAID (Google Advertising ID) mobile device IDs. Note that mobile device IDs cannot be combined with any other types of customer data.

Customer Match attributes

You can have a Customer Match list that stores the following attributes of its members:

lifetime_value_micros
The advertiser-defined lifetime value for the user, specified in micros.
lifetime_value_bucket
A value between 1 and 10 (inclusive) that represents the lifetime value bucket of the user, with 10 representing the highest value bucket.
To clear this attribute, provide a value of 0.

In order to upload UserData objects with these attributes, you must use an OfflineUserDataJob where the type is set to CUSTOMER_MATCH_WITH_ATTRIBUTES.

Customer Match considerations

When implementing Customer Match, keep the following points in mind:

  • It takes 6 to 12 hours for a list to be populated with members, so you'll most likely see an "In Progress" status (on the Google Ads UI) if you upload to an audience list more frequently than once every 12 hours.

  • The operations collection for each AddOfflineUserDataJobOperationsRequest can contain at most 100,000 elements. If you need to submit more than 100,000 operations for a job, send multiple requests with the same job resource_name.

  • Do not mix create and remove operations within the same OfflineUserDataJob. Doing so can result in a CONFLICTING_OPERATION error.

  • To completely replace the members of a user list with new members, order the operations in AddOfflineUserDataJobOperationsRequest in this sequence:

    1. Set remove_all to true in an OfflineUserDataJobOperation.
    2. For each new member, add a create operation setting their UserData in an OfflineUserDataJobOperation.

    When you run your job, the Google Ads API will first mark all current members of the list for removal, and then apply the create operations.

  • Operations are validated when uploaded to an OfflineUserDataJob. We recommend enabling partial_failure in an AddOfflineUserDataJobOperationsRequest so as to detect any problematic operations before running the job.

  • Errors encountered during the execution of an OfflineUserDataJob can be fetched using the offline_user_data_job report using the Google Ads Query Language. Note, however, that this report does not contain information about any failed matches; only hashes are compared when performing matches, so we cannot provide specific reasons for failures.

  • For privacy purposes, the user list size will show as zero until the list has at least 1,000 members. After that, the size will be rounded to the two most significant digits.

  • Upload at least 5,000 members to the list to ensure that ads start serving.

  • A crm_based_user_list can only be combined with another crm_based_user_list when using a logical_user_list. All the policies for crm_based_user_list will apply to the result user list.

  • If you attempt to create multiple jobs with the same external_id, the request will fail with an EXTERNAL_UPDATE_ID_ALREADY_EXISTS error.

  • Avoid simultaneously running multiple OfflineUserDataJob processes that modify the same user list (that is, multiple jobs whose CustomerMatchUserListMetadata.user_list point to the same resource name). Doing so can result in a CONCURRENT_MODIFICATION error since multiple jobs are not permitted to operate on the same list at the same time. This error can also occur if attempting to simultaneously modify a list through the Google Ads UI and Google Ads API.

Remove data from a Customer Match audience list

There are multiple ways to remove data from a Customer Match audience list:

Remove the list itself:

Remove all data from the list at once:

Remove individual users using identifiers:

  • Set the remove attribute on an OfflineUserDataJobOperation equal to a UserData object.
  • Add one or more UserIdentifiers to the user_identifiers[] repeated field.
  • A single user identifier can be used to remove a user from a list, even if more than one identifiers were submitted that match the user.
  • Note that remove operations cannot be mixed with create operations in a single job. Running such a job will fail with a CONFLICTING_OPERATION error.