A while ago, I wrote a really popular piece of content around tracking goal completions through WordPress Contact Form 7 (WPCF7). A lot has changed over the last couple of years — but the popular WordPress plugin is still one of our favourites.

Tracking events from WP Contact Form 7 in Google Analytics?

1. Tag managers and data layers

Well, firstly, the last few years has seen the rise in popular tag management containers such as Google Tag Manager abstract much of your on-site tracking code to the cloud for easier editing. This affects what many may know only as the “data layer”– and if you’re not in the know, I’d suggest reading this long form piece about Google Tag Manager by my colleague.

2. Plugin evolution

Clearly Takayuki is keen to move from the ability to add custom code into the plugin directly in the favour of custom DOM events (see all) before the end of 2018. DOM — the “document object model” — is best described as the resulting HTML document drawn by the HTML, CSS and JavaScript which runs as a page load. The resulting, dynamic, and potentially changing document, is the “DOM”.

Events can be “fired” in the DOM, and “handlers” can “listen” to these events. These listeners can then process additional scripts based on the outputs. And this is what’s happening here. If you’re unfamiliar with this terminology, then hang in as I’ve got a practical example for you below!

How to track WP Contact Form 7 events in Google Tag Manager

Through tapping into the DOM events WPCF7 registers, we’re able to move the snippets away from the plugin itself – into either your site’s JavaScript files, or arguably even better – into Google Tag Manager. The below snippets can be bundled into your scripts files, but in this tutorial moving forwards, I’ll assume you’ll be using Google Tag Manager only.

1. Getting started

Ensure you have Google Tag Manager installed. This may involve pestering your developers to add the tracking code to your website’s code. Or, it might involve simply adding a plugin (depending on your permissions). As of the time of writing this post, I recommend DuracellTomi’s Google Tag Manager for WordPress as it achieves a few extra cool features (authorship tracking, etc) too all bundled into the plugin code!

Ensure you’ve got a GTM account set up, and get your Container ID added into the plugin.

Also, for debugging, it’s nice to use a Chrome plugin called Tag Assistant by Google (but you can just type “dataLayer” into your browser’s console to view the stacked there, too). Download that for later.

2. Register your event listener in GTM

We’ll need one tag to register our “listener” and then we have a choice;

  1. Track all contact form 7 form fills as one custom event in Tag Manager
  2. Track each form as an individual custom event in Tag Manager – this tracks individual form IDs!

Register a new tag and set its trigger to “All Pages”. The type should be HTML and the snippets can be found below;

Option 1) For listening to all form completions and triggering only one event;

Option 2) For listening to each form completion and triggering an individual event per form;

This code snippet essentially registers an event listener on “all pages” (it’s simpler that way – room for optimisation if you have time!) for the custom event “wpcf7mailsent” and triggers a dataLayer custom event.

Our custom DOM listener tag, being triggered on “All Pages”

3. Register your custom triggers

If you’ve taken option 1 above, your event will be called ‘form_submitted’. For option 2 – our preferred route – then your custom events will be ‘form_submitted_{Form_ID}’ where Form_ID is replaced inline with your WordPress form ID. If you’re struggling to find this – just check in the image below;

WordPress Contact form 7 edit screen URL – including the WordPress Form ID

Using this second option gives more granularity in reporting and importantly through Google Tag Manager allows different tags to be fired on different form completions.

To register a new trigger, select “Triggers” from the left hand menu, then “New”. Configure your new “Custom Event” trigger similar to the settings below;

This will now trigger when custom events on the form ID 1000 is successfully submitted

4. Register your Google Analytics (or other) custom event tags

If you’re familiar with creating Google Analytics event tags, then you may want to skip ahead. Here’s how it’s done;

  • Click through to “Tags” from the main Tag Manager Workspace menu
  • Click “New”
  • Name your tag (something like): GA – Form 1000 submitted
  • Select type: Universal Analytics
  • Track type: Event
  • Category, Action, Label (something like): forms, submitted, 1000 (or even something more useful – “Business form” for example)
  • Select triggers: The one you made earlier

A completed custom Tag setup including a Google Universal Analytics custom event

5. Test your form!

You should be able to see your events in Google Analytics real time. Don’t forget to put your Google Tag Manager container into “Preview” mode like the below, and ensure you “Refresh” if any changes have been made.

Google Tag Manager in preview mode

In Google Tag Manager Preview Mode, you should see something like the below;

Example Tag Manager preview mode for debugging the event firing

And then this will translate into an event in Google Analytics, like so;

View your events live in Analytics under “Real Time > Events” for instant feedback when testing

From here, go ahead and set up custom Goals as you usually would. That’s it! You’ve now got a scalable WordPress Contact Form 7 & Google Tag Manager solution implemented!

Don’t forget to publish your Tag Container and leave preview modes. If you’ve got any questions, please let me know in the comments below!

Aaron Dicks

Performance Director

Performance Director of Impression. Search engine optimisation, paid media and web analytics consultant. Also programmer and digital all-rounder. @aarondicks

Aaron has specialist knowledge in SEO, PPC and Analytics Consultancy.

19 thoughts on “WordPress Contact Form 7 Event Listeners and Google Tag Manager

  1. Adam Stevens says:

    Thanks Aaron! Great article, really helpful

    1. matthias says:

      Hi, thanks for the article. Is it possible to track just the impression of a cf7 form?

  2. CehnadianBroncoFan says:

    first off – Great article. I do have one question. I have been trying to find which CF7 vars can be used as passthroughs in the code and have not been successful. For example a form ID is not really that helpful in reporting for me or my organization BUT form Title would be. So if I replaced event.detail.contactFormId with event.detail.contactFormTitle would it work?

    1. aarondicks says:


      I’m afraid it’s not that simple. You can see at this URL which variables are easily accessible through this event.


      What do you need the form name for?

      Perhaps you could localize() the names and data you need in an array on the page so that you can then reference it in this callback event?



  3. Tom McCracken says:

    Impressive article walking through the all steps with Tag Manager. I’ve found that even with tools like Tag Manager, most people still don’t setup goals for form submissions.

    I’ve been working on a project to removing all the coding, tag management, and even GA goal setup out of the process to make it as dirt simple as possible. If you get a chance, I would love your feedback: https://wordpress.org/plugins/cf7-intelligence

    1. aarondicks says:

      Thanks for the addition, Tom.

      I’m interested, how do you post to GA? Via ga(‘send’…, or otherwise?

      Would be cool to see a Google Tag Manager version, too, for non-code-savvy marketers to interact with.

      1. Tom McCracken says:

        It is an event. Basically, Intelligence will always trigger an “Form submission” event. The goals in GA are set to look for events with the goal name at the end. So to trigger a goal we change the event to “Form submission: [Goal name]”. This makes gives us a good way to standardize triggering goals on any kind of event such as email clicks.

        The core plugin does a lot more. You can get a good idea of how it all works here: https://intelligencewp.com/doc/jumpstart/

        It does work with the GTM embed. So you can use both together, although it doesn’t do anything with the data layer at the point.

        1. aarondicks says:

          Cool, thanks for clarifying. Nice work!

  4. Luke Miller says:

    A really helpful tutorial. Thank you very much. Can I please ask what does {{Impression Analytics}} refer to on your Tag ‘GA – Form 1000 submitted’?

    1. aarondicks says:

      Hi Luke, that’s just our Settings Variable name. Within that is our Google Analytics UA-XXXX code and a few other settings.
      If you go through the setup and here select ‘New Variable’ you’ll be able to see the settings required within for yourself!
      Thanks, Aaron

      1. Luke Miller says:

        Thank you.

  5. MatX24 says:

    Hi, I have a form and field of 4 answers. I want the user, after choosing the right answer, to be transferred to the website. Each response should have a different website.

    1. aarondicks says:

      I haven’t tested this, but in theory you could achieve this through this method.
      Within the event listener you can access the inputs like so

      var inputs = event.detail.inputs;

      (Full example here https://contactform7.com/dom-events/)

      Then you could test for the relevant inputs in that array and then use JavaScript to forward them on to the new destination page using one of the following options:

      // similar behavior as an HTTP redirect
      // similar behavior as clicking on a link
      window.location.href = “http://stackoverflow.com”;

      Read more on that here https://stackoverflow.com/questions/503093/how-to-redirect-to-another-webpage

      Hope this helps! Let me know how you get on!

  6. Marwan Nasr says:


    Thanks for all the info in your post.
    I’ve setup form tracking just fine thanks to your help however I have a requirement to add some variables to as we’re pushing the data layer through to GTM.
    For instance, this code :

    ‘event’: ‘gtm_event_prix’,
    ‘eventCategory’: ‘Get pricc=e’,
    ‘eventAction’: ‘From’, // Click is in header or body
    ‘eventLabel’: ‘Url’,// Page name
    ‘brandAwarness’: ‘Salon’,// User input in the form field
    ‘userSurface’: ‘Commerciale’, // User input in the form field


    Is it possible to track user input from CF7 and send it to GTM?
    If so, are variables the best way to do so?

    Thanks for your time,

    1. aarondicks says:

      Hi Marwan, you absolutely can do this! However, it depends how.

      From your code it looks like you know what you want your variables to be — that’s fine as they can be hardcoded.

      If you’re looking to access the input data as variables you’ll need to write some custom JavaScript to access these as the event.detail object won’t include everything you need.

      Start by looking at using dataLayer custom variables in Tag Manager (with the names from your code snippet) and research around that. The form will be accessible on the page when the event is fired so depending on your level of JS knowledge, you could just access the form field values like so if needed:


      Let me know how you get on!


      1. Marwan Nasr says:

        Hey Aaron,
        Thanks for getting back to me 🙂
        I’ll keep digging for now and will keep you posted.
        I’m mostly work in the front-end so this is a bit of a nebulous zone for me. I may end up hiring someone to give a hand :S Thx for your time 🙂

  7. Cecilia Blomqvist says:

    Hi Aaron, I am new to Google Tag manager. Thanks for a great tutorial!! I finally managed to set up tracking of all our forms. 🙂 However, I noticed in the preview of Google Tag Manager, in the left column with the header “Summary” in blue, that every click in each field of the form was registered as a “gtm.click”. I also received one “gtm.linkClick”. What is that? Will it screw up my click statistics?! Did I do something wrong? 🙂

    1. Aaron Dicks says:

      Hi Cecilia
      I think this is fine – That summary list just shows you all possible events which tags *could* fire on. If none fire, then it’s not a problem at all!
      Glad I could help you – please let me know if you have any other issues

  8. pierre says:

    Hi Aaron, Great tutorial thanks, I have this set up but now I want to be able create a trigger for different types of traffic, so say one from organic and the other from adwords, would that be possible?