Next Action Analyst

2026-07-23

GTM: How to Track Form Submissions With No Thank You Page (3 Working Setups)

You built a form conversion trigger in GTM based on the Thank You page URL, but the form doesn't redirect anywhere — it just shows a success message on the same page. Your trigger never fires, your conversions show zero, and every "how to track form submits in GTM" article you find assumes a page reload that isn't happening.

Why this happens

  1. Most common: The form submits via AJAX (Contact Form 7, Gravity Forms, WPForms, HubSpot forms, Typeform embeds, custom React/Vue forms) — there's no page load event for GTM to hook into, because the URL never changes.
  2. The existing trigger is still built on Page URL or Page Path "contains /thank-you" — a URL that will never exist for this form.
  3. A success message does appear in the DOM, but it's not consistently selectable, or it disappears too fast for GTM's Element Visibility polling to catch it.
  4. The form plugin does fire its own JavaScript event, but the GTM trigger is listening for the wrong event name, or the dataLayer push happens before the GTM container has loaded.
  5. Least common: Multiple forms live on the same page and the trigger fires on the wrong one because the selector or event isn't scoped to a specific form ID.

Fix, step by step

  1. Pick the pattern that matches your form: if a visible "Thank you for your submission" message appears in the DOM after submit, use Pattern A (Element Visibility). If the form plugin exposes a documented JS event (CF7's wpcf7mailsent, Gravity Forms' gform_confirmation_loaded, WPForms' wpformsAjaxSubmitSuccess), use Pattern C. If neither applies or you control the form's code, use Pattern B (manual dataLayer push).
  2. Pattern A — Element Visibility trigger: In GTM, create a new Trigger, Trigger Type = Element Visibility. Set Selection Method to CSS Selector and target the success message container (e.g. .form-success-message). Set "When to fire this trigger" to Once per element, and check Observe DOM changes since success messages are usually injected after page load.
  3. Pattern B — Custom Event via dataLayer push: Add a script (in your form's success callback, or via the plugin's hook) that pushes a dataLayer event on success. In GTM, create a Trigger, Trigger Type = Custom Event, Event name = the exact string you pushed (e.g. form_submit_success).
  4. Pattern C — Listen to the form plugin's own JS event: Add a Custom HTML tag that fires on All Pages, containing a listener that pushes to dataLayer when the plugin's native event fires. Then build a Custom Event trigger listening for that same pushed event name, exactly as in Pattern B.
  5. Scope to the right form if there are multiple on the page: add a Trigger condition matching the form ID, or read {{DLV - formId}} from the dataLayer push and filter on it.
  6. Attach your conversion tag (GA4 event, Ads conversion, etc.) to whichever trigger you built, and add a Trigger Exception if needed to avoid double-firing on page refresh.
  7. Publish the container version and test in GTM Preview mode before trusting the data.

Copy-paste template

PATTERN A — Element Visibility
Trigger Type: Element Visibility
Selection Method: CSS Selector
Element Selector: .form-success-message
Fires: Once per element
Advanced: Observe DOM changes = ON

PATTERN B — Manual dataLayer push (place in form success callback)
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  'event': 'form_submit_success',
  'formId': 'contact-form-main'
});

Trigger Type: Custom Event
Event name: form_submit_success

PATTERN C — Listen to plugin's native JS event (Custom HTML tag, fires on All Pages)
document.addEventListener('wpcf7mailsent', function(event) {
  window.dataLayer.push({
    'event': 'form_submit_success',
    'formId': event.detail.contactFormId
  });
}, false);

// Swap event name for your plugin:
// Gravity Forms: gform_confirmation_loaded
// WPForms: wpformsAjaxSubmitSuccess
// Elementor Forms: submit_success

Trigger Type: Custom Event
Event name: form_submit_success

How to verify it worked

Open GTM Preview mode, submit the form on the live page, and confirm the Summary panel shows your Custom Event or Element Visibility trigger firing exactly once, with the correct formId in the Variables tab if you're using one. Then check your GA4 DebugView (or the Ads/conversion tool you're feeding) to confirm the event lands with the right parameters before you publish.

Once the event is firing reliably, the harder work starts: knowing which form, on which campaign, actually deserves budget next. That's the layer Next Action Analyst adds on top of clean GTM data — turning form-submit events into a prioritized list of next actions instead of just another row in a report.

Stop reading dashboards. Start acting on them.
Next Action Analyst turns your campaign export into a prioritized list of changes to make tomorrow — with the numbers that justify each one.