LW IT Solutions
« Blog Overview /Digital Marketing/Tutorials / Tutorial: Implementing Google Ads Enhanced Conversions
This post in other languages:

Tutorial: Implementing Google Ads Enhanced Conversions

Tutorial: Implementing Google Ads Enhanced Conversions
Contents
  1. Step 1: Enabling the Feature in Google Ads
  2. Step 2: Capturing the Email Address
  3. Step 3: Creating the User-Provided Data Variable
  4. Step 4: Hashing and Transmission
  5. Step 5: Attaching to the Conversion Tag
  6. Sources

Google Ads Enhanced Conversions significantly improve measurement accuracy by recovering conversions that would otherwise be lost due to cookie restrictions or cross-device journeys. By securely transmitting hashed first-party customer data (such as an email address) to Google, the system can match this data against signed-in Google accounts, attributing the conversion to the correct ad click.

The following tutorial explains the process of capturing an email address after a purchase or lead generation, ensuring it is hashed properly, and sending it via Google Tag Manager (GTM).

Chain from the e-mail field in the DOM through normalisation and SHA-256 hashing to the em parameter in the Google Ads conversion tag
The chain from the visible field to the matched conversion: the address is normalised, hashed in the browser and only then sent as em — what leaves the page is a fingerprint, not an address.

Step 1: Enabling the Feature in Google Ads

Before any technical implementation begins, Enhanced Conversions must be enabled within the Google Ads account. This is done by navigating to the Conversions section, selecting the specific conversion action (e.g., Purchase or Lead), and checking the box to turn on Enhanced Conversions. The “Google Tag or Google Tag Manager” method should be selected.

Step 2: Capturing the Email Address

The core of the implementation is extracting the customer’s email address on the “Thank You” page. There are two primary methods to achieve this:

Method A: DataLayer (Recommended)

The most robust and reliable approach is pushing the email address directly into the DataLayer from the server or CMS. A standard DataLayer push upon a successful transaction looks like this:

<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  'event': 'purchase',
  'customerData': {
    'email': 'customer@example.com'
  }
});
</script>

In GTM, a Data Layer Variable must be created pointing to the key customerData.email.

Method B: CSS Selectors (Fallback)

If modifying the DataLayer is not possible, the email can be extracted directly from the website’s Document Object Model (DOM). If the email is displayed on the confirmation page (e.g., <span id="customer-email">customer@example.com</span>), a DOM Element Variable can be created in GTM. The selection method should be set to “CSS Selector” with the selector targeting the specific element (e.g., #customer-email).

Step 3: Creating the User-Provided Data Variable

Once the email is captured as a GTM variable, it must be formatted correctly for Google Ads.

  1. A new variable of the type User-Provided Data is created in GTM.
  2. The “Manual configuration” option is selected.
  3. The previously created email variable (from DataLayer or DOM) is assigned to the “Email” field.

Step 4: Hashing and Transmission

Privacy regulations require that personal data is never sent in plain text. A major advantage of using the GTM “User-Provided Data” variable is that it automatically applies the required SHA-256 hashing algorithm to the email address before transmission. No manual JavaScript hashing is required.

Step 5: Attaching to the Conversion Tag

The final step involves linking the configured data to the tracking tag.

  1. The existing Google Ads Conversion Tracking tag is opened.
  2. The box for “Include user-provided data from your website” is checked.
  3. The newly created User-Provided Data variable is selected from the dropdown menu.

The setup must be tested using GTM Preview Mode. When the conversion tag fires, the network request can be inspected to verify that the em (email) parameter is populated with a hashed string, confirming a successful, privacy-compliant implementation.

Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Get in Touch

Briefly describe your project or inquiry for a tailored response. This site is protected by reCAPTCHA.

4 comments

  1. Ryan Marsden

    Useful walkthrough — particularly the note that the hashing happens inside the variable, since half the implementations out there still ship a hand-written SHA-256 in a custom template.

    Method B is where our setup struggles. On the confirmation page the email arrives from an XHR after render, so the DOM variable resolves to an empty string when the tag fires. Is there an ordering guarantee I am missing, or is the DataLayer the only dependable route?

    1. Lukas Wojcik Author

      There is no ordering guarantee. A DOM variable is read at the moment the tag fires and never re-read; a value that arrives afterwards is simply not part of that request.

      The fix is not a better selector but a better trigger: fire the conversion on the event that carries the data — the same push that signals the purchase — rather than on the page view that happens to precede it. Where the data layer cannot be touched at all, a custom event pushed by the code that renders the address serves the same purpose.

      The reason this is worth chasing rather than accepting: an empty email field does not break anything visible. The tag fires, the conversion is counted, and only the enhancement is missing — so the conversion count looks healthy while match rates stay flat. The check that separates the two is the network request itself: the em parameter is either present with a 64-character hash or it is absent.

  2. Zofia Klimek

    Coming back to this after implementing it — the note that no manual hashing is required saved an argument with our developers.

    One thing I could not settle from the documentation: does the variable normalise before hashing? We also hash the same addresses in the CRM for a different platform,and I would like to be sure the two sides produce identical digests.

    1. Lukas Wojcik Author

      The variable normalises the documented fields — trimming whitespace and lowercasing an email address before it hashes. The risk therefore does not sit in the browser; it sits on the other side, in the CRM.

      Hashing is not case-insensitive, so Anna@Example.com and anna@example.com produce two completely unrelated digests. A CRM export that skips the lowercase step still hashes successfully, still uploads successfully, and matches nothing. No error appears at any stage — the only symptom is a match rate that sits near zero and gets blamed on the platform.

      Where two systems hash the same identifier, the normalisation rule belongs in a written specification rather than in each implementation’s habits: lowercase, trim, and one documented decision each for plus-addressing and phone number formatting. Those last two are not covered by the platform documentation, which is exactly why they have to be settled once instead of independently on both sides.

Write a comment

The email address is not published. Required fields are marked with an asterisk.

ALL ARTICLES & CATEGORIES

CCTV

Follow this category by RSS

Cloud & AI

Follow this category by RSS

Data Privacy

All 11 articles in this category Follow this category by RSS

Digital Analytics

All 44 articles in this category Follow this category by RSS

Digital Marketing

All 25 articles in this category Follow this category by RSS

IT & Networks

All 15 articles in this category Follow this category by RSS

Raspberry PI

Follow this category by RSS

Smart Home

All 11 articles in this category Follow this category by RSS

Web Development

Follow this category by RSS

WordPress Plugins & Tricks

Follow this category by RSS