How to track user logins, registrations and form interactions
GTM4WP can report three things your visitors do that WordPress itself knows about: filling in a form, logging in and registering an account. Each one becomes a data layer event that you can build a trigger on in Google Tag Manager.
All three are switched off by default. You find them together in the User events section of the settings screen.
This page describes GTM4WP 2.0.0 and newer. Where the legacy 1.x versions of the plugin behaved differently, the older behavior is marked with a bold GTM4WP 1.x: lead-in.
The events
| Event name | Fired when | Option |
|---|---|---|
gtm4wp.formElementEnter | The visitor moves the focus into a form field | Form fill events |
gtm4wp.formElementLeave | The visitor moves the focus out of a form field | Form fill events, narrowed by Only report fields the visitor filled in |
gtm4wp.userLoggedIn | An existing user has logged in on the frontend | User logged in |
gtm4wp.userRegistered | A new user has registered on the frontend | New user registration |
Switching the options on
Open Settings, then Google Tag Manager, and pick the User events section. The checkboxes sit in its Events group.
- Form fill events tracks movement between the fields of any form on your site.
- Only report fields the visitor filled in narrows the leave half of those events. It stays disabled until Form fill events is ticked.
- New user registration reports a registration completed on the frontend.
- User logged in reports a login completed on the frontend.
Tick the ones you need and save the settings. You do not have to configure anything else in WordPress.
GTM4WP 1.x: these options were on the Events tab, which also carried the YouTube, Vimeo and SoundCloud checkboxes. Those three moved to the Media events section in 2.0.0. Upgrading keeps the settings you had and every event name, so a container built against 1.x keeps working. The one option on this screen that 1.x did not have is Only report fields the visitor filled in, and it starts switched off, which is covered below.
Form fill events
With Form fill events on, the plugin loads its form tracking script on every frontend page. The script watches the focus move in and out of your form elements and pushes an event each time.
gtm4wp.formElementEnter fires when the focus arrives at an element, gtm4wp.formElementLeave when it leaves. The script covers input, select, textarea, button, meter and progress elements.
On its own the option looks at the focus and nothing else. It does not check whether the field holds a value, so a visitor who tabs through a form without typing anything still produces a full pair of events for every field along the way. The Only report fields the visitor filled in option below changes that.
The script listens on the document rather than on the individual forms, so a form that arrives after the page has loaded is covered as well. This includes forms in popups and forms loaded by AJAX.
Both events carry the same six keys:
| Data layer key | Value |
|---|---|
inputID | The id attribute of the element the visitor moved into or out of |
inputName | The name attribute of the element |
inputClass | The class attribute of the element |
formID | The id attribute of the form the element belongs to |
formName | The name attribute of the form |
formClass | The class attribute of the form |
When an attribute is missing, the plugin sends a readable placeholder instead of an empty value, so inputID holds (no input ID), formName holds (no form name) and so on. An element that is not part of any form gets the three form placeholders.
Alongside these six, both events also fill Google Tag Manager’s built-in Form variables, so a tag can read the form without a Data Layer Variable of its own.
The events describe the fields and not their content. The plugin does not read what the visitor typed into them.
Keep the volume in mind before you forward these events to an analytics tool. Every field a visitor touches produces two events, so a checkout form with twenty fields can produce forty pushes in a single page view. On most sites a trigger that fires on the first field of one specific form is more useful than one that forwards everything.
Developers can move the script out of the footer. The gtm4wp_event-form-move filter takes a boolean, and returning false loads it in the head instead. See the actions and filters page for the rest of them.
Only reporting fields the visitor filled in
Every field the visitor touches produces both events by default, whether they typed anything into it or not. On a long form that is a lot of noise. Someone who tabs from the top of a checkout down to the payment button produces a leave event for every field they passed through and filled in none of them.
The Only report fields the visitor filled in option changes the leave half. With it ticked, gtm4wp.formElementLeave fires only when both of these hold:
- the field was empty when the visitor entered it, and
- it holds a value when they leave it.
The event therefore marks the moment a field gets filled in. gtm4wp.formElementEnter is never filtered and keeps firing for every field, which leaves you both halves of the picture: the enter events count the fields a visitor touched, the leave events count the fields they filled in, and the gap between the two is where they stopped.
Text inputs, textareas and dropdowns are checked this way, and a value of nothing but spaces counts as empty. Checkboxes, radio buttons, buttons, meter and progress are always reported, because none of them has an empty state to begin with: a checkbox carries the same information ticked or unticked, and a button can only be clicked.
Two results of that rule are worth knowing before you switch the option on:
- A field that already held a value when the visitor entered it reports nothing when they leave it unchanged, because the visitor did not fill it in. This covers a field your theme pre-fills, a logged in customer’s saved email address on the checkout page, and a dropdown whose options all carry a value, which is never empty and so can never make the transition. A dropdown that starts on a
Choose...placeholder does make it. - Clearing a field reports nothing either. The option reports the moment a field gets filled in, not the value it happens to hold.
One more case follows from the same rule. When a field already has the focus before the tracking script finishes loading, the plugin never saw the visitor enter it and cannot tell whether it was empty at the time, so it reports no leave event for that first field. This applies to a form with an autofocus field on a slow connection, and to a site where an optimization plugin delays JavaScript until the first interaction.
The option is off by default and it is marked beta. Nothing about your form events changes until somebody ticks it.
GTM4WP 1.x: the legacy versions had no such option and always reported every field. Upgrading from 1.x therefore changes nothing here on its own. The 1.x settings never held a value for this option, so it arrives switched off, and your existing triggers keep receiving the same leave events they always did until you decide otherwise.
Reading the form with Google Tag Manager’s built-in variables
Both form events also fill the data layer keys behind Google Tag Manager’s built-in Form variables. A tag firing on gtm4wp.formElementEnter or gtm4wp.formElementLeave can therefore read the form straight from those variables, without you building a Data Layer Variable for it.
Built-in variables are switched off in a new container, so enable the ones you want first: open Variables, click Configure and tick them in the Forms group.
| Built-in variable | Holds | Our own key for the same thing |
|---|---|---|
| Form ID | The id attribute of the form | formID |
| Form Classes | The class attribute of the form | formClass |
| Form URL | The address the form posts to | none |
| Form Target | The target attribute of the form | none |
Google publishes no Form Name built-in variable, so the form’s name attribute has no counterpart here. Read it the way you always have, with a variable of type Data Layer Variable named formName.
The values follow what Google’s own form submission event carries rather than the readable placeholders the plugin puts in its own keys. Three differences follow from that:
- A missing attribute arrives as an empty string. In the same push,
formIDholds(no form ID)while Form ID is empty. That is deliberate: a built-in variable reporting(no form ID)would look like a real id to every tag reading it. - Form URL is the form’s action resolved into a full address. A form with no action attribute posts to the page it sits on, so that page is what the variable holds.
- A field that belongs to no form at all sends none of these four keys. Test for the presence of the variable rather than for an empty value.
One consequence is worth knowing before you rely on this. Google gives the Forms and the Clicks built-in variables the same underlying data layer keys, so on these two events Click ID and Click Classes report the form as well. Nothing on the plugin side can separate them. If your container has a tag that reads Click Classes on a broad trigger, check that the trigger does not also match the form events.
GTM4WP 1.x: the legacy versions filled none of the built-in variables. Tags built against 1.x read the form through Data Layer Variables on formID, formName and formClass, and those keys are unchanged, so nothing has to be rebuilt. The built-in variables are an addition next to them.
gtm4wp.userLoggedIn
The login request itself ends in a redirect and renders no page, so there is no data layer to push into at the moment the login happens. The plugin therefore sets a cookie named gtm4wp_user_logged_in, and pushes gtm4wp.userLoggedIn on the next frontend page view. It deletes the cookie at the same time, so each login produces exactly one event.
The push carries the event name and nothing else. To know who logged in, switch on the variables you need in the Visitor data group of the Page variables section. They are described on the user and visitor data page.
Where the event turns up depends on where your site sends the user after login. WordPress sends them to the dashboard by default, and the plugin does not run on admin screens, so the event waits for the first frontend page the user opens. If your login form redirects to a frontend page instead, the event fires there.
The cookie lasts for the browser session. If a user logs in and closes the browser before opening a frontend page, the plugin never pushes the event.
Only the login itself produces the event. A visitor whose session continues from an earlier visit does not.
gtm4wp.userRegistered
Registration works the same way. The plugin sets a cookie named gtm4wp_user_registered, pushes gtm4wp.userRegistered on the next frontend page view and deletes the cookie.
The event covers registrations completed on the frontend of your site. This includes WooCommerce account creation on the My account and checkout pages, and any registration form that goes through the standard WordPress registration.
A user account created by an administrator in the WordPress admin does not produce the event. That is deliberate, since an administrator adding an account is not a conversion.
When a registration flow also signs the user in, the plugin sets both cookies and both events fire on the same page view. gtm4wp.userLoggedIn comes first.
Building the trigger in Google Tag Manager
- Open your container, go to Triggers and create a new trigger.
- Choose Custom Event as the trigger type.
- Enter the event name, for example
gtm4wp.userLoggedIn, and leave This trigger fires on set to All Custom Events. - Save the trigger and assign it to your tag.
To catch both form events with one trigger, tick Use regex matching and enter the following event name:
gtm4wp\.formElement(Enter|Leave)
You read the six keys listed earlier with a Data Layer Variable named exactly like the key, so inputID, formID and the rest. For the form itself you can use the built-in Form variables instead.
Sending them to Google Analytics 4
Google Analytics 4 has recommended event names for two of these. Fire a GA4 event tag named login on gtm4wp.userLoggedIn and one named sign_up on gtm4wp.userRegistered. Both accept a method parameter that describes how the user signed in, which is worth filling in when your site offers more than one way.
The form events have no recommended counterpart. GA4 enhanced measurement already collects form_start and form_submit on its own, so check whether that covers what you need before you send anything extra. The GTM4WP events go field by field, which enhanced measurement does not, and with Only report fields the visitor filled in switched on they cut the volume down to something a GA4 property can carry: one leave event per field a visitor actually completed.
Ordering is worth a thought here. With the default settings the visitor variables are part of the first data layer push, so a tag firing on gtm4wp.userLoggedIn can read them. With the Cache-safe data layer option on, they arrive in a gtm4wp.visitorData event of their own, which usually comes later than gtm4wp.userLoggedIn. Read the login state from the gtm4wp.visitorData event in that case, as described on the triggers for visitor, device, customer and cart data page.
What these events do and do not carry
The form events carry the id, the name, the class and, for the form, the address it posts to. They do not carry the values a visitor typed into them. This holds with Only report fields the visitor filled in switched on as well: the plugin reads the value to decide whether to fire the event, and never puts it into the data layer.
The login and registration events carry no user data. They report that a login or a registration happened and say nothing about the person. Every user variable comes from a separate option that you switch on yourself.
Both cookies are session cookies. They hold the value 1, they carry the HttpOnly flag so no script can read them, and they are gone as soon as the event has fired. See the GDPR page for how this fits into the rest of the plugin.
If an event does not arrive
- Check the option first. All of them are off by default.
- For the login event, open a frontend page after logging in. The event does not fire on the WordPress dashboard.
- For the registration event, remember that an account created in the WordPress admin does not count.
- If the enter events arrive but the leave events do not, check whether Only report fields the visitor filled in is on. A pre-filled field, a dropdown with no empty option and a field the visitor leaves empty all report the enter event and nothing else while it is.
- If the events arrive but a built-in Form variable is empty in Preview mode, check that you enabled it under Variables, Configure. An enabled variable is still empty when the form has no such attribute, and it is absent entirely when the field belongs to no form.
- For the form events, check that the page loads the
gtm4wp-form-move-trackerscript. An optimization plugin that delays JavaScript until the first interaction can hold it back long enough to miss the first field. - In Preview mode, look at the row of the event itself. The values are not on the Container Loaded or DOM Ready rows.
- If you renamed the data layer, the form script pushes into the renamed one. A Data Layer Variable that still expects
dataLayerfinds nothing there.
Related pages
See also how to track Contact Form 7 submissions for form submissions rather than form interactions, user and visitor data for the variables that describe the logged in user, and how to set up triggers for visitor, device, customer and cart data for the events those variables arrive in.

