Skip to content

Events & Tracking ​

Easy Forms dispatches custom events for hooking into the form lifecycle and can automatically capture URL tracking parameters for attribution.

Available Events ​

form:submit ​

Dispatched when the form submission begins, before any validation or API calls.

Event Detail:

  • submitData: Object containing all form field values
  • formHandle: The form handle as set in Statamic e.g. "contact"
  • formId: This is the same as the form handle unless you also use the instance setting.

Example:

javascript
document.addEventListener('form:submit', (event) => {
    const { submitData, formHandle } = event.detail;
    console.log(`Form ${formHandle} is submitting with:`, submitData);
});

form:success ​

Dispatched when the form submission succeeds and receives a successful response.

Event Detail:

  • data: Response data from the server
  • submitData: Object containing the submitted form field values
  • formHandle: The form handle as set in Statamic e.g. "contact"
  • formId: This is the same as the form handle unless you also use the instance setting.

Example:

javascript
document.addEventListener('form:success', (event) => {
    const { data, submitData, formHandle } = event.detail;
    // Redirect, show custom message, analytics tracking, etc.
    window.location.href = '/thank-you';
});

form:error ​

Dispatched when the form submission fails due to validation errors, server errors, or ReCAPTCHA issues.

Event Detail:

  • errors: Object containing validation errors (field name as key)
  • error: String error message (for fatal errors)
  • status: HTTP status code (when available)
  • fatalError: Boolean indicating if this is a non-recoverable error
  • formHandle: The form handle as set in Statamic e.g. "contact"
  • formId: This is the same as the form handle unless you also use the instance setting.

Example:

javascript
document.addEventListener('form:error', (event) => {
    const { errors, fatalError, status, formHandle } = event.detail;
    
    if (fatalError) {
        console.error('Fatal error occurred');
    } else {
        // Handle field-specific validation errors
        console.log('Validation errors:', errors);
    }
});

Usage Notes ​

  • All events bubble up through the DOM, so you can listen at the document level or on specific form elements
  • Events are dispatched from the form element itself (this.$refs.form)
  • The formHandle parameter allows you to identify which form triggered the event when multiple forms exist on the page
  • Use event.detail to access all event-specific data

Analytics Examples ​

Here are some examples of how to use these events for analytics tracking, in this instance we will use Google Analytics 4.

Global Listener (Vanilla JS) ​

This example sets up a global listener that tracks all form submissions. This is useful if you want to track all forms on your site without modifying each one.

javascript
// Listen for form success event
window.addEventListener('form:success', (event) => {
    const { data, submitData, formHandle } = event.detail
    
    // Google Analytics 4 (gtag.js)
    if (typeof gtag !== 'undefined') {
        gtag('event', 'form_submission', {
            'event_category': 'Form',
            'event_label': formHandle,
            'form_name': formHandle,
            'user_email': submitData.email || 'unknown',
        })
    }
})

Inline Listener (Alpine.js) ​

You can also listen for events directly on the form element using Alpine.js. This is useful if you want to track specific events for a single form.

For this to work you need to publish the form views and edit the resources/views/vendor/easy-forms/form/component.antlers.html file to add the x-on:form:success.window listener.

antlers
<form
    method="{{ method }}"
    action="{{ action }}"
    x-data="formHandler('{{ handle }}')"
    x-ref="form"
    x-on:submit.prevent="formSubmit"
    x-on:fields-changed="updateSubmitData($event.detail)"
    x-on:form:success.window="
        if ($event.detail.formHandle === '{{ handle }}') {
            gtag('event', 'form_submission', {
                'form_name': '{{ handle }}',
                'user_email': $event.detail.submitData.email
            })
        }
    "
    data-csrf-token="{{ csrf_token }}"
    aria-label="{{ title }}"
>
    {{# ... rest of the form ... #}}
</form>

URL Tracking Parameters ​

Easy Forms automatically captures URL tracking parameters (like Google Ads click IDs) and includes them in form submissions for conversion attribution.

How It Works ​

  1. Add a tracking_id hidden field in your form's Blueprint.
  2. A visitor lands on a page with tracking parameters (e.g., ?gclid=abc123&gbraid=xyz456)
  3. Each parameter value is stored in its own cookie for 30 days
  4. When the form is submitted, all captured parameters are automatically submitted as a query string (e.g., gclid=abc123&gbraid=xyz456)

Setup ​

Add a hidden tracking_id field to your form blueprint:

yaml
- handle: tracking_id
field:
    type: text
    input_type: hidden
    display: Tracking ID

That's it! Tracking capture is automatic when this field exists.

Default Tracked Parameters ​

ParameterDescription
gclidGoogle Click Identifier
gbraidGoogle Ads app campaign identifier (iOS)
wbraidGoogle Ads web-to-app identifier

Custom Parameters ​

To track additional parameters (like UTM tags), add data-track-params to your form element. This requires a ./easy-form-tag#tag-parameters:

html
<form data-track-params="gclid,gbraid,wbraid,utm_source,utm_medium,utm_campaign" ...>

Cookie Details

Each tracked parameter is stored in its own cookie:

  • Name pattern: ef_track_{param} (e.g., ef_track_gclid, ef_track_gbraid)
  • Expiration: 30 days (matches Google Ads attribution window)
  • Path: / (site-wide)
  • SameSite: Lax

URL parameters always take precedence over stored cookies, allowing fresh clicks to override previous attribution data.