Contact form 7 is yet another pretty popular form plugin for WordPress. What do good marketers do with forms? They track submissions, say, with Google Analytics and then measure the overall performance: where do those conversions come from? which forms perform better? etc.

Nowadays, one of the most popular ways how to track any interaction on the website is …surprise surprise!… Google Tag Manager. If for some reason, you haven’t tried it before, you definitely should (here are some reasons why).

Anyway, back to the topic. Contact Form 7 is no exception and you can definitely track it with Google Tag Manager. You can either read this long (but very useful) guide and learn more about the magic of form tracking, or you can just continue reading this blog post because today I’ll explain how Contact Form 7 event tracking with Google Tag Manager works.

Why this guide?

I’ve already seen some guides on the web covering Contact Form 7 event tracking with GTM, however, they have some issues/limitations:

  • Some offer an inaccurate solution (by using Click Trigger!!!? which is a big NO in form tracking)
  • While others are giving not enough. I mean, they show how to track form submissions (which is good) but I’ve found that it’s pretty easy to also get values of each submitted form field which can give you much more insight!

Interested? I hope that after reading the previous paragraph you felt like this:


By the way, if you have any feedback, please leave it in the comments and I’ll get back to you.


things to keep in mind

This solution works with AJAX-based forms (built with Contact Form 7) which means that if the page does not refreshed after the successful submission, then go ahead and continue reading.

Also, this guide is mainly targetted at single-page forms. Multi-page forms fire events of successful form submissions after each step. Their tracking is not covered in this guide but I don’t want to leave you on thin ice so here are some hints/directions.

  • For multi-page forms, ese the auto-event listener mentioned in this blog post (#1 chapter)
  • What I’ve noticed so far, is that usually each step has its own form ID, therefore you can track submissions by updating the custom cf7submission trigger. Set it to fire when form ID equals to XX (replace XX with the ID of the last step’s form).


Contact Form 7 DOM events

In their documentation, Contact Form 7 developers have listed several DOM events that are dispatched after a particular form interaction occurs:

  • wpcf7invalid — Fires when an AJAX form submission has completed successfully, but mail hasn’t been sent because there are fields with invalid input.
  • wpcf7spam — Fires when an AJAX form submission has completed successfully, but mail hasn’t been sent because a possible spam activity has been detected.
  • wpcf7mailsent — Fires when an AJAX form submission has completed successfully, and mail has been sent.
  • wpcf7mailfailed — Fires when an AJAX form submission has completed successfully, but it has failed in sending mail.
  • wpcf7submit — Fires when an AJAX form submission has completed successfully, regardless of other incidents.

To make Contact Form 7 event tracking come true, at first, I tried listening to wpcf7submit event but what I ended up with was that this DOM event was being dispatched even if required form fields contained errors. As a result, I switched to wpcfmailsent event.


1. Contact Form 7 Event Tracking: Auto-Event Listener

The first ingredient of the form tracking is a piece of code which will be listening and waiting for a successful form submission. That code is also known as an auto-event listener. The listener will be waiting for wpcf7mailsent DOM events and if one occurs, it will push some useful data to the Data Layer (event name, form id, values of all form fields).

Compared to other solutions found online, this will not only create a Data Layer event called cf7submission but will also return a full response, an array of every form field and its value. More on this – a bit later.

In order to implement this code, go to your Google Tag Manager account, then a container and create a Custom HTML tag which fires only on those pages which contain forms. Let’s say that in our case, form is in the footer of each page, so we’ll fire it on All Pages.

Contact Form 7 Listener in Google Tag Manager


1.1. Test the listener

Before we continue, it’s crucial to test if the listener is capable of capturing a successful form submission. In GTM, enable Preview and Debug mode and the orange notification bar will appear. If it doesn’t, view this troubleshooting guide.

Preview and Debug mode

Now, go to the website where the form is located and refresh the page. A debugging console will appear at the bottom of the screen where you can see which tags have and haven’t fired. Fill in all form fields and submit the form.

If everything worked smoothly, you should see a cf7submission event in the Preview and Debug Console (just like in the screenshot below).


More importantly, click that cf7submission event and go to the Data Layer tab. What you’ll see is an array of all form fields, field names and their values (which were entered by a visitor). So not only will you be able to track successful form submission, but you’ll also have a chance to capture form field values too. P.S. Keep in mind that Google Analytics does not allow you to store PII on their platform (but that data might be sent to other tools).

wpcf7 data layer


2. Variables and a Trigger

So what have we done so far? Well, we have some data in the Data Layer that we could to use:

  • cf7submission is a Data Layer event which should be turned into a trigger. No tag will fire without a trigger.
  • Just for demonstration purpose, we’ll also want to capture a subject line of a form submission and pass it to Google Analytics later on. We can fetch that field’s value by creating a Data Layer variable.

If you want to turn some Data Layer event (in our case, it’s cf7submission) into a tag-firing condition, you need to create a custom trigger.

Custom Event trigger in GTM

Now, it’s variables’ turn. Let’s take a closer look what’s happening in the Data Layer after cf7submission event occurred. In addition to event and formId, Contact Form 7 listener also pushed the response which is an array containing 5 objects. Each object represents a form field. In JavaScript, indexes start from 0, not from 1, so if we want to fetch your-subject field’s value (which is the third object), we’ll have to choose index 2, not 3.

arrays and objects

In one of my previous blog post, how to pull data from the Data Layer, I’ve explained 3 different data structures:

  • When all data points are on the same level
  • When there are different levels (children-parents)
  • And when there are arrays.

In this case, we have to choose the 3rd option, pulling data from arrays in the Data Layer. In order to do so, we first have to define the parent key, which, in this case, is response. Then we have to set the index (in order to tell Google Tag Manager in which object we are interested). This time, it’s 3 (because it is the 4th object in the array, an in JavaScript indexes start from 0 (0, 1, 2, 3, 4)). And, finally, we choose the final key – field’s value.

As a result our Data Layer Variable name is response.3.value

dlv - form subject in Contact Form 7

Another variable which I would recommend to create is formId. If you have several forms on a website, it will help you distinguish which form was submitted (and you won’t have to create separate triggers and tags for each Contact Form 7).

dlv - formId

Save both variables and test them. The best way to do it is to refresh the Preview and Debug mode, refresh the page with the Contact Form 7 and try submitting it again.

After that, click cf7submission event once again and go to Variables tab. You should be looking for two newly created Data Layer Variables.

In the screenshot below, everything is working just as we expected: one variable contains the actual subject line while other one fetched ‘9′ which is the ID of my test form. If you got undefined value, double check if you entered all variable settings correctly. Remember that Data Layer variable names are case-sensitive.

Data Layer variable in the GTM Preview and Debug mode

If you are still facing issues with any of those two variables, read this guide how to pull data from the Data Layer.


3. Google Analytics Event Tag

First two steps of the Contact Form 7 event tracking are done! Now, let’s send the form submission event to Google Analytics via Universal Analytics tag with the following settings:

  • Track Type: Event
  • Event Category: Form Submission
  • Event Action: Form ID: {{dlv – formId}} (when the actual event occurs, form ID will be replaced, so the final result could be Form ID: 9
  • Event Label: Form Subject: {{dlv – Form Subject}} (the same applies here: when the actual event is dispatched, the Data Layer Variable will be replaced with its value, e.g. Form Subject: This is a test.
  • Do not forget to add the Custom Trigger we’ve created earlier.

Google Analytics Event Tag - Form Submission


4. Let’s test

Save all changes, refresh the Preview and Debug mode, go to the website where the Contact Form 7 is implemented and refresh that page as well. Submit it and take a closer look at what’s happening in the Preview Console. Expected result: Universal Analytics event tag must fire only when the form was submitted successfully.

GTM preview mode - GA Tag fired

Once the tag appears in the section of fired tags, head over to Google Analytics Real-time event reports.

Google Analytics Real-time report



The last step of the Contact Form 7 event tracking: create a Google Analytics Goal. Log in to your Google Analytics account and:

  1. Go to the desired account’s Admin section
  2. Choose a view you’re interested in
  3. Go to Goals and press NEW GOAL

Google Analytics Admin section

Now, enter the following settings:

  • Template: Custom
  • Goal name: enter anything you like. In the example below, I’ve entered Form submission
  • Type: Event

GA Goal - part 1

Finally, enter Goal details:

  • Event Category equals to Form submission
  • If you have more forms on a website and you wish to track ONLY THIS ONE, then you can additionally set the rule: Event Action equals to Form ID: 9

If you leave other fields empty, they will not be checked.

GA Goal - part 2


Contact form 7 event tracking: final words

So there you have it. In this blog post, I’ve explained how to track single-page AJAX-based Contact Form 7. The process is similar to other WordPress Plugin, Gravity Form:

  • Implement a custom auto-event listener which listens to successful form submissions.
  • Create variables and a custom trigger.
  • Set up a Universal Analytics event tags which pushes the event of a successful form submission to Google’s servers.
  • Finally, set up Google Analytics goal.

As it was mentioned before, you might face some difficulties if your form is multi-page (consists of two or more steps and each one of them refreshes the page). What I’ve noticed so far, is that usually each step has its own form ID, therefore you can track submissions by updating the custom cf7submission trigger. Set it to fire when form ID equals to XX (replace XX with the ID of the last step’s form).

If you still face issues with Contact Form 7 event tracking (by using GTM), read this guide: 6 ways how to track form submissions with Google Tag Manager. I bet you’ll find something useful.

Julius Fed

Head of Developer Operations at Omnisend. I am highly interested in Google Tag Manager, Google Analytics, Adwords, Email marketing, Email Deliverability, Digital Marketing in general. You can follow me on Twitter.