Tutorial: How to Track WPForms AJAX Submissions & Subjects in GA4
Published on | Web Analytics • WordPress • Analytics & Tracking
Because I choose to have AJAX (updating without a page reload) activated on my WPForms (a WordPress plugin), it can complicate things a bit. But nothing that can’t be tracked. Here is a tutorial on how to do it.
Phase 1: The “Listener” (The Bridge)
We know that standard GTM form triggers don’t work with WPForms AJAX (because the page doesn’t reload). I also personally tested and know that using plugins such as “Code Snippets” was less reliable than putting the code directly into GTM (for this task specifically). Also, using GTM directly is the more robust method (less plugin reliance, better timing control).
Step 1: Create the Custom HTML Tag
- Where: GTM > Tags > New > Custom HTML.
- Trigger: All Pages. (Or in my case, “Custom – cookie_consent_update”)
- Tag name: (This can be whatever. I chose “Script – WPForms Listener”)
- What it does: It waits for jQuery, listens for the “Submit” action to grab the subject, and then waits for the specific WPForms “Success” signal to push that data to GTM.
- The Code: (My form ID for the contact form is 398 and the Subject field is field_5, please replace with your form ID and field number)
<script>
// Wait for jQuery to be fully loaded
var tryWPFormsTrack = setInterval(function() {
if (typeof jQuery !== 'undefined') {
clearInterval(tryWPFormsTrack);
jQuery(document).ready(function($){
var formID = 398;
var capturedSubject = "";
// 1. LISTEN TO THE SUBMIT ACTION
$('#wpforms-form-' + formID).on('submit', function(){
capturedSubject = $('#wpforms-' + formID + '-field_5').val();
});
// 2. LISTEN FOR THE SUCCESS MESSAGE
$(document).on('wpformsAjaxSubmitSuccessConfirmation', function(e, id, response){
// Check if we have a captured subject waiting
if (capturedSubject !== "") {
window.dataLayer.push({
'event': 'contact_form_success',
'contact_subject': capturedSubject
});
// Reset to prevent double-firing
capturedSubject = "";
}
});
});
}
}, 500);
</script>
Phase 2: The GTM Configuration (The Translation)
Once the script above pushes the data, GTM needs to “catch” it and format it for Google Analytics.
Step 2: Create the Variable
- Where: Variables > User-Defined Variables > New > Data Layer Variable.
- Name:
dlv - contact_subject - Data Layer Variable Name:
contact_subject - Why: This reads the specific text (e.g., “Project Inquiry”) from the code in Step 1.
Step 3: Create the Trigger
- Where: Triggers > New > Custom Event.
- Name:
Event - Contact Form Success - Event Name:
contact_form_success - Why: This tells the GA4 tag exactly when to fire (only after the script confirms success).
Step 4: Create the GA4 Tag
- Where: Tags > New > GA4 Event.
- Event Name:
generate_lead - Event Parameters:
- Parameter Name:
topic(orlead_subject) - Value:
{{dlv - contact_subject}}
- Parameter Name:
- Trigger:
Event - Contact Form Success - Why: This bundles the “Subject” data into the packet sent to Google.
Phase 3: The GA4 Configuration (The Reporting)
Finally, if needed, we tell GA4 to stop ignoring that extra “topic” data and store it in a way we can analyze.
Step 5: Register Custom Dimension
- Where: GA4 > Admin > Custom definitions > Create custom dimension.
- Dimension Name:
Contact Subject - Scope:
Event - Event Parameter:
topic(Must match Step 4 exactly). - Why: This ensures the data appears in the reports (like in “Traffic Acquisition” or “Explore”) instead of disappearing into the void.
And the Bow on Top
Remember to do your steps to follow GDPR. I use the cookie banner Cookiebot so I applied the settings for that into these newly created tags too.