Skip to main content
AnalyticsLearner

Module 7

Enhanced Conversions: user-provided data + SHA-256 normalised hashing

Implement Google Ads Enhanced Conversions by hashing user-provided data (email, phone, name) with SHA-256 before sending to Google.

enhanced-conversionsgoogle-adssha256gtm

What this does

Google Ads Enhanced Conversions improves conversion measurement by sending hashed user-provided data (email, phone, name, address) alongside your conversion events. Google matches the hashed data against signed-in Google accounts to attribute conversions that would otherwise be missed.

The data must be normalised and hashed with SHA-256 before sending. Google does not accept unhashed data for Enhanced Conversions.

Normalisation rules (Google's requirements)

Email:       trim whitespace, lowercase
Phone:       E.164 format (+12025551234), strip spaces/dashes
First name:  trim whitespace, lowercase
Last name:   trim whitespace, lowercase

SHA-256 hashing function

// Works in modern browsers (Web Crypto API) and Node.js 16+
async function hashField(value) {
  const normalised = value.trim().toLowerCase();
  const encoded = new TextEncoder().encode(normalised);
  const hashBuffer = await crypto.subtle.digest('SHA-256', encoded);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
}

dataLayer push for Enhanced Conversions

// On conversion (checkout complete, form submit, etc.)
async function pushEnhancedConversion({ email, firstName, lastName, phone }) {
  const [hashedEmail, hashedFirst, hashedLast, hashedPhone] = await Promise.all([
    email ? hashField(email) : null,
    firstName ? hashField(firstName) : null,
    lastName ? hashField(lastName) : null,
    phone ? hashField(normalisePhone(phone)) : null,
  ]);
 
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    event: 'conversion',
    enhanced_conversion_data: {
      email: hashedEmail ?? undefined,
      first_name: hashedFirst ?? undefined,
      last_name: hashedLast ?? undefined,
      phone: hashedPhone ?? undefined,
    },
  });
}
 
function normalisePhone(phone) {
  // Remove all non-digit characters except leading +
  const digits = phone.replace(/[^\d+]/g, '');
  // Ensure E.164 format - this is a simplified normalisation
  // Your implementation should handle country codes correctly
  return digits.startsWith('+') ? digits : `+${digits}`;
}

GTM configuration

In GTM, configure the Google Ads Conversion Tag with Enhanced Conversions:

  1. Enable "Enhanced conversions" on the tag
  2. Set "Enhancement data source" to "Data Layer"
  3. Map the dataLayer variables:
    • Email: enhanced_conversion_data.email
    • First name: enhanced_conversion_data.first_name
    • Last name: enhanced_conversion_data.last_name
    • Phone number: enhanced_conversion_data.phone

GTM will send the hashed values to Google Ads when the conversion fires.

TypeScript version

interface UserData {
  email?: string;
  firstName?: string;
  lastName?: string;
  phone?: string;
}
 
async function buildEnhancedConversionData(user: UserData): Promise<Record<string, string>> {
  const result: Record<string, string> = {};
  const entries: [string, string | undefined][] = [
    ['email', user.email],
    ['first_name', user.firstName],
    ['last_name', user.lastName],
    ['phone', user.phone],
  ];
 
  const hashed = await Promise.all(
    entries.map(([, value]) => (value ? hashField(value) : Promise.resolve(null)))
  );
 
  entries.forEach(([key], i) => {
    if (hashed[i]) result[key] = hashed[i]!;
  });
 
  return result;
}

Consent requirement

Enhanced Conversions requires ad_storage: 'granted' and ad_user_data: 'granted'. Configure the Google Ads conversion tag in GTM to require both consent types. Do not send Enhanced Conversions data when either signal is denied.

The free Enhanced Conversions Container has the full GTM setup with hashing variables pre-built.

Free container for this module

Enhanced Conversions Container

GTM container implementing Google Ads Enhanced Conversions with SHA-256 normalised hashing of user-provided data. Includes the data layer schema, variable definitions, and the conversion tag configuration.

Get the container →