Enhanced Conversions Not Working? Complete Fix Guide (Google Ads)

Your Google Ads Enhanced Conversions aren't tracking properly. Learn how to diagnose and fix implementation issues for both GTM and gtag.js setups.

Google AdsEnhanced ConversionsGTMconversion trackingfirst-party data

Enhanced Conversions are supposed to improve your Google Ads conversion accuracy by 5-15%. But if they’re not set up correctly, you’re getting zero benefit—and you might not even know it. Here’s how to diagnose and fix Enhanced Conversions issues.

What Enhanced Conversions Actually Do

Before debugging, understand what you’re debugging:

Enhanced Conversions capture first-party customer data (email, phone, address) at conversion time, hash it, and send it to Google. Google matches this against signed-in user data to attribute conversions that would otherwise be lost due to:

  • Cookie restrictions
  • Cross-device journeys
  • Privacy browser settings

Key point: If the data isn’t being captured or hashed correctly, Enhanced Conversions silently fail—no errors, just missing attribution.

Check 1: Verify Enhanced Conversions Are Enabled

First, confirm the feature is actually on:

In Google Ads:

  1. Go to Tools & Settings → Conversions
  2. Click on your conversion action
  3. Scroll to “Enhanced conversions”
  4. Verify it shows “On”

What the Status Should Show:

  • “Recording conversions”: Working
  • “Inactive”: Needs troubleshooting
  • “No recent data”: Data not being received

If status is “Inactive,” continue debugging below.

Check 2: Verify Data Is Being Sent

For GTM Implementation:

Open GTM Preview mode and check your conversion tag:

  1. Click on your Google Ads Conversion tag
  2. Look for “User-provided data” section
  3. Verify values are populated:
Email: j***@example.com (hashed automatically)
Phone: +1555******
First Name: J*** (if included)

If “User-provided data” is empty, the data layer isn’t providing the values.

For gtag.js Implementation:

Check the network request:

  1. Open DevTools → Network
  2. Filter by “googleads”
  3. Find the conversion request
  4. Look for em= (email) or ph= (phone) parameters
// Should see something like:
em=a1b2c3d4e5... (SHA-256 hash)

If these parameters are missing, data isn’t being captured.

Check 3: Data Layer Configuration (GTM)

For GTM Enhanced Conversions, you need data in one of two places:

Option A: Automatic Collection (CSS Selectors)

GTM can automatically find form fields on your page:

  1. In your Google Ads Conversion tag, click “Include user-provided data from your website”
  2. Choose “Automatic collection”
  3. GTM looks for fields matching common patterns

Why automatic collection fails:

  • Non-standard field names
  • Fields inside iframes
  • Dynamic form rendering
  • Multi-step checkouts

Push user data explicitly:

// On your conversion page (e.g., order confirmation)
dataLayer.push({
  'event': 'purchase',
  'user_data': {
    'email': 'customer@example.com',      // Will be hashed by GTM
    'phone_number': '+15551234567',        // E.164 format
    'address': {
      'first_name': 'John',
      'last_name': 'Doe',
      'street': '123 Main St',
      'city': 'New York',
      'region': 'NY',
      'postal_code': '10001',
      'country': 'US'
    }
  }
});

In GTM, Configure the Tag:

  1. Edit your Google Ads Conversion tag
  2. Check “Include user-provided data from your website”
  3. Select “Manual configuration” or “Code”
  4. Create a Data Layer Variable for user_data.email
  5. Map it to the Email field
Variable: dlv_user_email
Data Layer Variable Name: user_data.email

Check 4: Data Format Requirements

Enhanced Conversions are strict about data formats. Invalid data is silently dropped.

Email Requirements:

// CORRECT formats:
'email': 'john.doe@example.com'           // Lowercase
'email': 'JOHN.DOE@EXAMPLE.COM'           // Will be lowercased by GTM

// INCORRECT formats:
'email': 'john.doe@example.com '          // Trailing space - FAILS
'email': ' john.doe@example.com'          // Leading space - FAILS
'email': ''                               // Empty string - FAILS
'email': null                             // Null - FAILS

Fix: Trim whitespace before pushing to data layer:

const email = formData.email.trim().toLowerCase();

Phone Requirements:

// CORRECT format (E.164):
'phone_number': '+15551234567'            // Country code, no spaces/dashes

// INCORRECT formats:
'phone_number': '555-123-4567'            // Missing country code - FAILS
'phone_number': '(555) 123-4567'          // Formatting characters - FAILS
'phone_number': '+1 555 123 4567'         // Spaces - FAILS

Fix: Normalize phone numbers:

function normalizePhone(phone, countryCode = '1') {
  const digits = phone.replace(/\D/g, '');
  if (digits.length === 10) {
    return `+${countryCode}${digits}`;
  }
  if (digits.length === 11 && digits.startsWith(countryCode)) {
    return `+${digits}`;
  }
  return `+${digits}`;
}

Address Requirements:

'address': {
  'first_name': 'John',           // Required: No numbers
  'last_name': 'Doe',             // Required: No numbers
  'street': '123 Main Street',    // Full street address
  'city': 'New York',             // City name only
  'region': 'NY',                 // State/province code
  'postal_code': '10001',         // No dashes for US
  'country': 'US'                 // ISO 2-letter code
}

Check 5: gtag.js Implementation

If you’re using gtag.js directly (not GTM):

Basic Setup:

// Enable Enhanced Conversions globally
gtag('config', 'AW-XXXXXXXXX', {
  'allow_enhanced_conversions': true
});

// Set user data BEFORE conversion event
gtag('set', 'user_data', {
  'email': 'customer@example.com',
  'phone_number': '+15551234567'
});

// Then fire the conversion
gtag('event', 'conversion', {
  'send_to': 'AW-XXXXXXXXX/XXXXXXXXXXX',
  'value': 99.99,
  'currency': 'USD',
  'transaction_id': 'ORDER12345'
});

Common gtag.js Mistakes:

Wrong: Setting user_data AFTER conversion:

// WRONG ORDER:
gtag('event', 'conversion', {...});  // Conversion fires first
gtag('set', 'user_data', {...});     // Data set too late - IGNORED

Wrong: Using wrong property name:

// WRONG:
gtag('set', 'userData', {...});      // camelCase - WRONG
gtag('set', 'user-data', {...});     // Hyphen - WRONG

// CORRECT:
gtag('set', 'user_data', {...});     // Underscore - CORRECT

Check 6: Hashing Issues

Enhanced Conversions require SHA-256 hashing. In most cases, Google handles this automatically—but there are exceptions.

When Google Auto-Hashes:

  • GTM with “Include user-provided data” enabled
  • gtag.js with user_data object
  • Google Ads API with unhashed fields

When You Must Pre-Hash:

  • Measurement Protocol
  • Offline conversion imports
  • Some server-side implementations

Correct hashing:

async function sha256Hash(value) {
  const encoder = new TextEncoder();
  const data = encoder.encode(value.trim().toLowerCase());
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// Usage:
const hashedEmail = await sha256Hash('customer@example.com');
// Result: 7c0bca...

Critical: Normalize BEFORE hashing:

  • Lowercase
  • Trim whitespace
  • Remove extra spaces
  • Apply format rules (phone E.164, etc.)

Check 7: Verification in Google Ads

Even if implementation looks correct, verify data is being received:

Conversion Diagnostics:

  1. Google Ads → Tools → Conversions
  2. Click your conversion action
  3. Click “Diagnostics” tab
  4. Look for Enhanced Conversions status

What Each Status Means:

  • “Enhanced conversions active”: Working correctly
  • “No enhanced conversion data received”: Implementation broken
  • “Enhanced conversion data received, processing”: Recently set up, wait 48-72 hours
  • “Limited data received”: Partial implementation (some conversions missing data)

Tag Coverage Report:

  1. Tools → Tag coverage
  2. Check Enhanced Conversions column
  3. Should show percentage of conversions with enhanced data

Healthy setup: 70%+ of conversions should have enhanced data.

Check 8: Common Implementation Mistakes

Mistake 1: Enhanced Conversions on All Conversions

Enhanced Conversions only work for conversions where you have user data. Don’t enable them for:

  • Page view “conversions”
  • Button click conversions
  • Any conversion without user PII

Mistake 2: Duplicate Conversion Tags

If you have multiple conversion tags firing:

  • Only one should have Enhanced Conversions enabled
  • Duplicates can cause data mismatches

Mistake 3: User Data on Wrong Page

Enhanced Conversions need data on the CONVERSION page, not the form submission page:

// WRONG: Data on form submission, conversion on thank-you page
// Form page: dataLayer.push({ user_data: {...} })
// Thank-you: dataLayer.push({ event: 'purchase' })  // No user_data!

// CORRECT: Data and conversion on same page (or data persisted)
// Thank-you: dataLayer.push({
//   event: 'purchase',
//   user_data: {...}
// });

Mistake 4: Testing with Fake Data

Enhanced Conversions validate data format. Using obviously fake data:

// Google may reject:
'email': 'test@test.com'           // Common test email
'phone_number': '+11111111111'     // Obviously fake

Use realistic test data for verification.

Debugging Checklist

Run through this checklist:

  • Enhanced Conversions enabled in Google Ads
  • Conversion tag has “Include user-provided data” checked
  • Data layer includes user_data object
  • Email is properly formatted (trimmed, lowercase)
  • Phone is E.164 format with country code
  • Data is available BEFORE conversion fires
  • GTM Preview shows user data in conversion tag
  • Network request includes hashed parameters
  • Google Ads diagnostics shows data received
  • No duplicate conversion tags

Enhanced Conversions Implementation Template

Here’s a complete, working implementation:

Data Layer Push (on confirmation page):

// Get user data from your confirmation page
const orderData = {
  transactionId: 'ORDER-' + Date.now(),
  value: 99.99,
  currency: 'USD',
  email: document.getElementById('customer-email').value,
  phone: document.getElementById('customer-phone').value,
  firstName: document.getElementById('first-name').value,
  lastName: document.getElementById('last-name').value
};

// Normalize and push
dataLayer.push({
  'event': 'purchase',
  'transaction_id': orderData.transactionId,
  'value': orderData.value,
  'currency': orderData.currency,
  'user_data': {
    'email': orderData.email.trim().toLowerCase(),
    'phone_number': normalizePhone(orderData.phone),
    'address': {
      'first_name': orderData.firstName.trim(),
      'last_name': orderData.lastName.trim()
    }
  }
});

GTM Variables:

Variable: dlv_user_email
Type: Data Layer Variable
Name: user_data.email

Variable: dlv_user_phone
Type: Data Layer Variable
Name: user_data.phone_number

GTM Conversion Tag:

  • Tag type: Google Ads Conversion Tracking
  • Conversion ID: AW-XXXXXXXXX
  • Conversion Label: XXXXXXXXXXX
  • Check: “Include user-provided data from your website”
  • Configuration: Manual
  • Map variables to fields

Still Not Working?

Enhanced Conversions failures are often subtle—the implementation looks correct but data isn’t matching. If you’ve followed this guide and conversions still show “No data received”:

  1. The data format might have edge cases we haven’t covered
  2. Multiple tracking scripts might be conflicting
  3. Server-side or consent issues might be blocking data

Get a free conversion tracking audit and we’ll analyze your specific implementation. We see dozens of Enhanced Conversions setups weekly and can identify issues that generic guides miss.