WordPress forms

Contact Form 7 Listener for GTM: GA4, Enhanced Conversions and Meta CAPI

Tracks real Contact Form 7 submissions in GTM from wpcf7mailsent, separates validation errors, spam blocks and mail failures, and passes clean email and phone to ad platforms.
EC-ready, Spam-aware, CAPI dedupe, Tracks failures

Free and MIT licensed. Paste it into a GTM Custom HTML tag. No plugin or code change on the site.

At a glance

Version

3.3.0-cf7.1

Updated

October 28, 2026

Success event

cf7_form_success

Failure event

cf7_form_failed

Detection

wpcf7mailsent + data-status="sent"

Redirects

Yes: pagehide fallback and same-domain thank-you recall

Enhanced Conversions

Yes: email, phone, name, address, optional SHA-256

Dependencies

None

Tag size

39.8 KB

License

MIT

What lands in your dataLayer

One clean event per real lead

Every success carries an event ID for Meta deduplication, the detection method that fired, and normalized contact fields you can map straight into Enhanced Conversions. Keep the PII keys out of GA4.

				
					{
  event: "cf7_form_success",
  ec_event_id: "uuid-v4",
  ec_detection_method: "confirmation_event",
  ec_tracker_version: "3.3.0-cf7.1",
  ec_name: "Jane Doe",
  ec_first_name: "Jane",
  ec_last_name: "Doe",
  ec_email: "jane@example.com",
  ec_phone: "+15551234567",
  form_url: "https://example.com/contact",
  form_cta: "Send",
  form_platform: "cf7",
  form_position: "top",
  form_index: 1,
  form_id: "5",
  ec_submit_attempt: 1,
  ec_time_to_submit_s: 42,
  ec_fast_submit: false,
  ec_first_source: "google",
  ec_first_medium: "cpc",
  ec_click_id: "Cj0K...",
  ec_click_id_type: "gclid"
}
				
			

Why this listener exists

Most Contact Form 7 recipes listen for wpcf7mailsent and push an event with nothing in it. They also ignore the other outcomes CF7 reports: validation errors, spam blocks and mail-server failures.

This listener uses CF7’s own DOM events, reads field values from the event itself, keys fields by your form tags (your-name, your-email) and reports each failure type separately.

Most form tracking fires on a button click or a thank-you page view. Clicks count validation failures and repeat clicks. Thank-you page views count refreshes, back-button visits and bookmarked links. This listener waits for Contact Form 7’s own success signal, so the event is much closer to a real lead.

How it detects a real submission

cf7_form_success fires on the first of these success paths:

  • The wpcf7mailsent DOM event
  • The form’s data-status changing to sent
  • A same-domain thank-you page, matched to data stored at submit
  • Page unload inside the submit window with no error showing (inferred)

cf7_form_failed fires on wpcf7invalid, wpcf7spam and wpcf7mailfailed, each with its own detection method, and only after the visitor has interacted with the form.

Every event carries ec_detection_method, so you can segment reports by how each lead was detected.

ec_detection_method Event What it means
confirmation_event Success The platform’s own success event fired
confirmation_class Success The form gained the platform’s success class
stored_recall Success Same-domain thank-you page, matched to data stored at submit
pagehide Success The page unloaded inside the submit window with no error showing (fallback)
validation_message Failure A validation message rendered after the visitor interacted
spam_blocked Failure CF7 blocked the submission as spam
mail_failed Failure CF7 accepted the form but its mail server failed to send
error_class Failure The form gained the platform’s error class

Install it in Google Tag Manager

  1. Download the GTM tag above, or copy cf7-form-tracker.gtm.html from the GitHub repository.
  2. In GTM, create a Custom HTML tag and paste the file in. It already includes the <script> wrapper and a production config block (debug: false, rawFields: false).
  3. Trigger it on All Pages (Page View), or on Consent Initialization if your consent setup needs the tracker available early.
  4. Create a Custom Event trigger for cf7_form_success. Use the regex ^cf7_form_(success|failed)$ if you also want failures.
  5. Create Data Layer Variables for the keys you need, then attach your GA4, Google Ads, Meta or server-side GTM tags to the trigger.
  6. Open Preview, submit a real test form and confirm one cf7_form_success. Then publish.

Retire any old click or thank-you page conversion for the same form, otherwise each lead is counted twice. Do not run this listener and the Universal tag on the same page.

Platform notes

  • CF7 internal fields (_wpcf7*), the honeypot, file uploads and reCAPTCHA tokens are excluded.
  • A CF7 mail failure means the visitor did submit. Decide whether your reporting counts mail_failed as a lead.
  • Debug API: window._ecCf7Tracker.status().

Events and dataLayer keys

Key What it holds
event cf7_form_success, cf7_form_failed, ec_form_interaction (first real input) or ec_tracker_initialized (script loaded)
ec_event_id UUID per event. Pass it to Meta as the event ID so browser and CAPI events deduplicate
ec_detection_method Which success or failure path fired (see above)
ec_email, ec_phone Email lowercased and validated, phone in E.164. Removed when PII consent is denied
ec_name, ec_first_name, ec_last_name Name, split into first and last where possible
ec_company, ec_street, ec_city, ec_region, ec_postal_code, ec_country Address and company fields for Enhanced Conversions, when the form has them
form_id, form_platform, form_cta Form identifier, platform name and submit button text
ec_submit_attempt, ec_time_to_submit_s, ec_fast_submit Attempt number, time from first input to submit, and a bot hint for very fast submits
ec_failed_fields On failure events: which fields failed validation
ec_first_source, ec_last_source, ec_click_id First and last touch attribution with gclid, gbraid, wbraid, fbclid, msclkid or ttclid
ec_pii_redacted true when PII consent is denied and PII keys were stripped

Using it for Enhanced Conversions and Meta CAPI

  • Google Ads Enhanced Conversions: map ec_email, ec_phone and the name and address keys into a User-Provided Data variable on your conversion tag.
  • Meta Pixel and CAPI: send ec_event_id as the event ID on both the browser and server event so Meta counts the lead once.
  • GA4: do not send ec_* PII to GA4. Its terms prohibit PII in event parameters. Send form_id, form_platform and ec_detection_method instead.

Configuration and consent

Edit the config block at the top of the tag:

Key Default Notes
debug false Console logs. Testing only
hashPii false Adds ec_email_sha256 and ec_phone_sha256 (needs HTTPS)
rawFields false Leaves ec_raw_fields out of the payload
dedupe true Suppresses a repeat success for the same form and person within 5 minutes
strictSuccess false true drops inferred successes (pagehide, form_removed)
defaultCountryCode '1' Phone E.164 fallback. A country field on the form takes priority
countryCodeField '' Exact field name that holds an ISO2 or dial code
redactFields [] Extra field names to strip. Password, card, SSN and IBAN fields are always stripped

The tracker auto-detects Google Consent Mode v2, OneTrust and Cookiebot. With analytics consent denied, nothing fires and nothing is stored, and events raised in the meantime are replayed if consent is granted. With PII consent denied, events fire without contact data. Any other CMP can be wired in with window.EC_FORM_CONSENT_CHECK. If no CMP or override is found, the tracker assumes full consent, so match it to your own legal requirements.

Test it before you publish

  • Submit a valid form. Expect one cf7_form_success.
  • Submit with a required field empty. Expect cf7_form_failed and no success event.
  • Fix the error and resubmit. Expect one success.
  • Refresh the confirmation or thank-you page. Expect nothing new.
  • Run window._ecCf7Tracker.status() in the console to see version, consent state, attached forms and the last event.

Known limitations

  • CF7 add-ons that replace the AJAX submit can change which events fire. Test on the live page.
  • A redirect to a different domain cannot use same-domain recall.
  • Bot or spam submissions that pass the platform’s own validation still count as success.
  • Phone normalization is best-effort.

Changelog

  • 3.3.0-cf7.1: first public standalone release, cut from the Universal tracker v3.3.0. Same core: consent gate with replay, PII redaction, optional SHA-256 hashing, 5-minute dedupe, ec_event_id, attribution, failure diagnostics and strictSuccess.

Feedback and field notes

Used this listener? Tell others what worked: your platform version, setup, or a tip. Found a bug? Open an issue on GitHub for a faster fix. Comments are reviewed before they appear.

Leave a Reply

Your email address will not be published. Required fields are marked *

On this page

Want it installed and verified?

We install the listener, wire GA4, Google Ads Enhanced Conversions and Meta CAPI, and check the numbers against your CRM.

Keep going

More GTM form listeners

Multi-platform

Universal GTM Form Tracker: One Tag for Nine Form Platforms

One GTM tag that detects the form platform on the page and tracks real confirmations for Gravity Forms, Elementor Pro, Contact Form 7, WPForms, GoHighLevel, Unbounce, SwipePages, Kartra and Squarespace.
9 platforms, One tag, CAPI dedupe, Container import
Embedded form builders

Jotform Listener for GTM: Track Redirecting Forms Without Thank-You Page Triggers

Tracks Jotform submissions in GTM even when the form redirects to a thank-you page, and never counts a refresh, back button or direct visit to that page.
Redirect-safe · EC-ready (source embeds) · CAPI dedupe · 88 tests
v3.3.0-jotform.1
WordPress forms

Gravity Forms Listener for GTM: GA4, Enhanced Conversions and Meta CAPI

Tracks real Gravity Forms submissions in GTM, including AJAX confirmations, postback pages and same-domain thank-you redirects, with hashed email and phone for Enhanced Conversions.
EC-ready · Redirect-safe · CAPI dedupe · Tracks failures

When the numbers still do not match

Your form fires. Does the conversion match the CRM?

A listener fixes detection. If Google Ads, Meta and GA4 still disagree with your actual leads, the problem is usually elsewhere in the container, the consent setup or the CRM hand-off.