
January 20, 2025
Prevent Duplicate Form Submissions with Google Tag Manager
With Google Tag Manager, you can track various user interactions, including form submissions, and send this data to Google Analytics 4 or another analytics platform for deeper insights. But what happens when a user submits the same form multiple times or repeatedly refreshes the “Thank You” page? These duplicate submissions can skew your data!
In this blog post, I’ll explain how to prevent duplicate form submissions with Google Tag Manager.

Table of Contents
Here’s what you will learn in this article
- Preventing duplicates
- Create a variable to capture the form ID
- Create the Custom HTML Tag
- Create a variable to capture if the user has previously submitted the form
- Update the form_submission event trigger
- Limitations
- Final Words
Preventing duplicates
If you’ve set up an event to track when a user is redirected to a “Thank You” page (e.g., the URL contains /thank-you/) after successfully submitting a form, you might run into an issue where GTM triggers the event if the page is refreshed.
This happens because Google Tag Manager continues to fire the event every time the page reloads, resulting in duplicated submissions in your data.
The good news is, there’s a simple solution! You can prevent duplicate event triggers by storing a unique identifier–like the form ID–in the browser’s local storage (with a few additional steps).
We will construct this identifier using a custom HTML tag and then create another variable that checks whether the form ID is contained in the identifier’s value when a form is submitted. If it is not, GTM will trigger the form_submission event. If it is, meaning the user has already submitted the form, GTM will not trigger the event.
Let’s take it step-by-step.
Create a variable to capture the form ID
For this example, the form ID is available in the URL (maybe it is for you too). To capture this information, you can create a URL variable (this could also be the page path or a data layer variable, anything that is unique to the form).
In GTM, click on “Variables” in the left-side navigation and select “New”.
Under Variable Configuration, select “URL”.
For the Component Type, choose “Query”.
You must enter the Query Key exactly as shown in the URL. In this example, we need the “form_id” query parameter.
Save this variable as “url – form_id”, and it’s ready to use in the custom HTML tag!
Create the Custom HTML Tag
Next, we will create a custom HTML tag to store the form_id in the browser’s local storage.
In Google Tag Manager, go to Tags in the left-hand navigation and select “New”.
Under the Tag Configuration, click “Custom HTML”.
In the input box, paste the code below:
<script> (function() { var formIdentifier = "REPLACE THIS"; // REPLACE THIS WITH A GTM VARIABLE; var submittedForms = localStorage.getItem("gtm_submitted_forms"); if (submittedForms) { submittedForms = JSON.parse(submittedForms); if (submittedForms.indexOf(formIdentifier) === -1) { submittedForms.push(formIdentifier); localStorage.setItem("gtm_submitted_forms", JSON.stringify(submittedForms)); } } else { localStorage.setItem("gtm_submitted_forms", JSON.stringify([formIdentifier])); } })(); </script>
You must replace the “REPLACE THIS” section with the name of the URL variable created above, e.g. {{url – form_id}}.
Name this tag “cHTML – store form id in local storage” and save it without adding a trigger (we will address this next).
Trigger the Custom HTML Tag
As mentioned, we are not building a traditional trigger for the custom HTML tag. We want this tag to fire AFTER GTM triggers the form_submission and the data is sent to a vendor (e.g., Google Analytics 4). We can actually do this from the form_submission GA4 event tag (or whatever vendor you’re using).
Go to your GA4 event tag that captures the form_submission event, scroll down to Advanced Settings > Tag Sequencing, check the “Fire a tag after GA4 event – form_submission”, and select the previously created cHTML tag from the dropdown.
The idea is that once the form_submission event fires and sends data to Google Analytics 4, the custom HTML tag stores the form ID in the browser’s local storage.
Now, we want to preview and check that the form ID is in your local storage. Click the “Preview” button located on the top-right of your GTM container.
You will need to complete the form submission on your site and then access the browser’s developer tools (right-click on the page and select “Inspect”)
Go to “Application”, find “Local storage” on the left-hand side, select your domain and enter “gtm_” in the search box.
You should see the gtm_submitted_forms key, containing a list of form IDs (there will just be one to start with).
This confirms that the custom HTML works as intended.

Create a variable to capture if the user has previously submitted the form
Ok, now that we have a way to store the IDs of forms that a user has submitted, we need to create a variable that checks whether the ID of the form the user is currently submitting is contained in local storage. This variable will return true if the form ID exists in local storage under the gtm_submitted_form key, and false if it does not.
To do this, create a new variable and select “Custom JavaScript” for the Variable Configuration.
In the input box, paste the code below:
function() { var formIdentifier = "REPLACE THIS"; // REPLACE THIS WITH A GTM VARIABLE var submittedForms = localStorage.getItem("gtm_submitted_forms"); if (submittedForms) { submittedForms = JSON.parse(submittedForms); if (submittedForms.indexOf(formIdentifier) !== -1) { return true; } } return false; }
Where it says “REPLACE THIS”, enter the name of the form ID variable you previously created, e.g. {{url – form id}}.
Name the variable “cjs – is form submission duplicate” (the answer to this question will be true or false).
To test the variable, go to your site without refreshing the page and delete the gtm_submitted_forms key (right-click and select “Delete”). We are doing this to test that we get a false value when we submit the form since it will be, according to the local storage, the first time we have submitted it.
Back in GTM, click Preview. When the website opens, submit the form and go to Tag Assistant. Select the “DOM Ready” event and go to the Variables tab. Check the value of the cjs – is form submission duplicate variable (it should be false).
Refresh the “Thank You” page and check that the variable is now true (since we have submitted the form twice now).
If everything goes according to plan, you are now ready to update the form_submission event to track only the initial submission of a form.
Update the form_submission event trigger
The final step is to update the trigger for the form_submission event so that it only triggers when the cjs – is form submission duplicate variable is false.
In GTM, go to the form_submission event and click on the firing trigger under Triggering.
Under the Trigger Configuration, add a new condition that “cjs – is form submission duplicate” must contain “false”.
To test this, go to your site without refreshing the page and delete the gtm_submitted_forms (just as we did before). We are doing this to test that Google Tag Manager triggers the form_submission event since no form IDs will be stored in local storage.
Preview your container and submit the form on your site. Back in Tag Assistant, go to the DOM Ready event and check that GTM has triggered the form_submission event (you might see an Unknown Variable Type for your tag, which you can just ignore).
Refresh the page and check that GTM has not triggered the event under “DOM Ready” since the form ID is now in the local storage, and the custom JavaScript variable will be true.
What if the user completes a different form? You can test it out by going to a different form on your site and completing it. Open the browser’s developer tools and go to Application > Local storage.
Search “gtm,” and you will see that the gtm_submitted_forms value now contains two form IDs.
Back in Tag Assistant, click the DOM Ready event and check that GTM triggered the form_submission event (since this is a completely different form than the one before).
Once you are confident that everything is set up properly, publish all changes in the container and follow proper naming conventions.
Limitations
One limitation to consider is that local storage is confined to individual sub-domains, so if you’re working across multiple sub-domains, you might want to consider modifying this approach to use cookies instead.
Ideally, you would get a developer to help you implement a data layer event to track form submissions. With their help, you can ensure the event is triggered only once, even if the user refreshes the page, preventing any duplicate submission in your data.
Prevent Duplicate Form Submissions with Google Tag Manager: Final Words
So there you have it! While involving a few steps, this is a pretty simple method for ensuring you do not get duplicate form submission events. It also highlights how helpful JavaScript can be, which you can learn more about in my JavaScript for GTM course.
Let me know in the comments below if you have any additional questions or thoughts!

0 COMMENTS