Skip to main content

Contact Form 7 GTM Event Listener

Track Contact Form 7 (CF7) form submissions in Google Tag Manager using the wpcf7mailsent event. Fire GA4 events, Google Ads conversions, and Meta pixels on successful submissions.

contact-form-7cf7wordpressformsgtmga4lead-generation

Event fired

cf7submission

Contact Form 7

Overview

Contact Form 7 (CF7) is the most widely-used WordPress form plugin, powering millions of contact forms worldwide. This listener hooks into CF7's native wpcf7mailsent DOM event to push structured data into the GTM dataLayer the moment a form submission succeeds, letting you fire any analytics or advertising tag without modifying theme files.

Event fired: cf7submission Trigger type: Custom Event Credit: Julius Fedorovicius (Analytics Mania)

Why Use This Listener

Without ListenerWith Listener
No way to track form submissions in GTM nativelyFull conversion tracking in GA4, Google Ads, Meta
Must use GTM's Form Submit trigger (unreliable)Event fires only on confirmed email send
No form ID data availableformId and full field response data captured
Can't distinguish between multiple formsEach form submission identified by unique formId

CF7 does not natively push to the dataLayer. The GTM built-in Form Submit trigger fires on button click, before validation. This listener fires after the email has been sent, making it the accurate conversion signal.

Common Use Cases

  • Lead generation tracking, Know exactly when a prospect submits a contact request
  • Multi-form conversion segmentation, Track which of your 5 different contact forms converts best
  • Google Ads conversion import, Send confirmed form submissions as conversion actions
  • Meta (Facebook) Pixel lead events, Fire Lead standard events to power retargeting audiences
  • GA4 funnel analysis, Include form submission as a milestone in your conversion funnel
  • Form abandonment analysis, Combine with scroll/time triggers to identify drop-off

How It Works

CF7 dispatches the DOM event wpcf7mailsent on the document when the server confirms the email was sent. The listener uses addEventListener to catch this event, extract the form ID and field values from event.detail, and push them to the dataLayer.

mermaid
sequenceDiagram
    participant U as User
    participant CF7 as Contact Form 7
    participant JS as Event Listener
    participant DL as dataLayer
    participant GTM as GTM
    participant GA4 as GA4

    U->>CF7: Clicks Submit
    CF7->>CF7: Validates + Sends Email
    CF7->>JS: Dispatches wpcf7mailsent
    JS->>DL: dataLayer.push({event: "cf7submission"})
    DL->>GTM: Trigger fires
    GTM->>GA4: Sends form_submit event

GTM Setup Guide

Step 1: Create the Custom HTML Tag

  1. Open Google Tag ManagerTagsNew
  2. Tag type: Custom HTML
  3. Paste the code below
  4. Trigger: All Pages (or DOM Ready, see note below)

Step 2: Create the Custom Event Trigger

  1. Go to TriggersNew
  2. Trigger type: Custom Event
  3. Event name: cf7submission
  4. This trigger = fires only on CF7 successful submissions

Step 3: Create DataLayer Variables

Create two Data Layer Variables in GTM:

Variable NameData Layer Variable NameDescription
DLV – CF7 Form IDformIdThe unique CF7 form ID
DLV – CF7 ResponseresponseArray of all form field values

Step 4: Attach Your Tags

Connect your GA4, Google Ads, or Meta tags to the cf7submission trigger.

Installation

html
<!-- GTM Custom HTML Tag: CF7 Event Listener -->
<!-- Trigger: All Pages (Pageview) -->
<script>
document.addEventListener('wpcf7mailsent', function(event) {
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    'event': 'cf7submission',
    'formId': event.detail.contactFormId,
    'response': event.detail.inputs
  });
});
</script>

Note on trigger timing: If CF7 script loads asynchronously, fire this listener on Window Loaded instead of DOM Ready to ensure the CF7 form object is available.

Example Implementation

Basic: Form Submit Tracking

javascript
document.addEventListener('wpcf7mailsent', function(event) {
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    'event': 'cf7submission',
    'formId': event.detail.contactFormId,
    'response': event.detail.inputs
  });
});

Advanced: Extract Specific Fields

javascript
document.addEventListener('wpcf7mailsent', function(event) {
  // Extract individual field values
  var inputs = event.detail.inputs;
  var email = '';
  var name = '';
  
  inputs.forEach(function(input) {
    if (input.name === 'your-email') email = input.value;
    if (input.name === 'your-name') name = input.value;
  });

  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    'event': 'cf7submission',
    'formId': event.detail.contactFormId,
    'response': inputs,
    'userEmail': email,
    'userName': name
  });
});

Data Layer Output

Successful Submission

json
{
  "event": "cf7submission",
  "formId": "1234",
  "response": [
    { "name": "your-name", "value": "John Smith" },
    { "name": "your-email", "value": "john@example.com" },
    { "name": "your-message", "value": "Hello, I'd like to enquire about..." }
  ]
}

Trigger Configuration

Single Trigger (All CF7 Forms)

Trigger Type: Custom Event Event Name: cf7submission Fires On: All Custom Events

Per-Form Trigger (Specific Form Only)

Trigger Type: Custom Event Event Name: cf7submission Condition: DLV - CF7 Form ID equals 1234 Fires On: Some Custom Events

Variables to Capture

GTM Variable NameDL KeyTypeExample Value
DLV – CF7 Form IDformIdData Layer Variable"1234"
DLV – CF7 ResponseresponseData Layer VariableArray of inputs

To access individual fields from the response array, use a Custom JavaScript Variable:

javascript
function() {
  var response = {{DLV - CF7 Response}};
  if (!response) return '';
  for (var i = 0; i < response.length; i++) {
    if (response[i].name === 'your-email') return response[i].value;
  }
  return '';
}

GA4 Mapping Recommendations

GA4 EventParameterGTM Variable
generate_leadform_idDLV – CF7 Form ID
generate_leadform_nameHard-coded or look-up table
generate_leadmethod"contact_form_7"
generate_leaduser_emailCustom JS Variable (extract from response)

GA4 Configuration Example:

Event Name: generate_lead Parameters: - form_id → {{DLV - CF7 Form ID}} - form_type → "contact_form_7" - method → "web_form"

Debugging

Check in GTM Preview Mode

  1. Open GTM Preview mode
  2. Submit a CF7 form on your site
  3. In the preview panel, look for a cf7submission event in the Events tab
  4. Click it and verify formId and response are populated

Common Issues

ProblemLikely CauseFix
Event not firingCF7 script not loaded when listener runsChange listener trigger to Window Loaded
formId is undefinedWrong DLV key nameCheck exact spelling: formId (capital I)
Fires on failed submissionsUsing wrong approachwpcf7mailsent only fires on successful sends, no fix needed
Multiple fires per submissionDuplicate listenersCheck for duplicate GTM containers or conflicting scripts

Browser Console Test

Open DevTools → Console and paste:

javascript
document.dispatchEvent(new CustomEvent('wpcf7mailsent', {
  detail: { contactFormId: '999', inputs: [{name:'test', value:'hello'}] }
}));

You should see the event appear in the GTM preview dataLayer panel.

Best Practices

  1. Use form-specific triggers, If you have different forms for different lead types (contact, demo, newsletter), create separate triggers using the formId condition to fire different GA4 events or different conversion labels
  2. Hash PII before sending, If capturing email/name in the dataLayer for enhanced conversions, use SHA-256 hashing: crypto.subtle.digest('SHA-256', ...)
  3. Set CF7 "on sent OK" class, In CF7 settings, add a sent response class so you can also style confirmation visually
  4. Combine with scroll depth, Track how far users scroll before contacting you for UX insights
  5. Test with spam filters, CF7's Flamingo or Akismet might block some submissions; test across form validation scenarios

Performance Considerations

  • Impact: Negligible, the listener attaches a single DOM event listener at page load
  • Event volume: One event per successful form submission
  • No polling, Purely event-driven, zero CPU overhead between submissions

Related Listeners

Example Business Scenarios

Scenario 1: B2B SaaS Lead Qualification

A SaaS company has 3 CF7 forms: "Request Demo" (ID: 100), "Contact Sales" (ID: 101), "General Inquiry" (ID: 102). They create 3 separate conversion actions in Google Ads, each mapped to the respective formId. This lets them see which form generates the highest-quality demos.

Scenario 2: Law Firm Conversion Tracking

A law firm tracks all CF7 submissions as generate_lead events in GA4. They then build an audience of people who submitted the contact form and target them with Google Display retargeting showing client testimonials.

Scenario 3: Agency Multi-Client Reporting

A digital agency manages 20 client WordPress sites, all using CF7. They deploy the same GTM container across all sites. The formId variable lets them filter by form in GA4 explorations to report conversions per client.

FAQ

Q: Does this work with CF7 AJAX submissions? A: Yes. wpcf7mailsent is dispatched after the AJAX call completes and the email is sent.

Q: What if I use CF7 with reCAPTCHA? A: The listener fires after reCAPTCHA validation passes and the email sends, so only genuine submissions are tracked.

Q: Can I track form starts (not just completions)? A: Yes, use GTM's built-in Element Visibility trigger on the CF7 form container, or listen to the wpcf7invalid event to capture validation failures.

Q: Does this work with multisite WordPress? A: Yes, each form has a unique contactFormId. Deploy via GTM and it works across all multisite installations.

Q: How do I get the form name (not just ID)? A: CF7 doesn't expose the form name in the event, use a GTM Lookup Table variable that maps form IDs to human-readable names.

Q: What happens if the email fails to send? A: wpcf7mailsent only fires on successful sends. wpcf7invalid fires on validation errors. wpcf7spam fires when spam is detected.