How to Capture UTM Values in Shopify Forms (2026)

Last updated
•
Expert reviewed
•
5 min read

Key takeaways

  • UTM parameters in a URL (utm_source, utm_medium, utm_campaign) can be read with JavaScript’s URLSearchParams and saved to hidden form fields.
  • This lets you know which ad, email, or campaign generated each contact form submission.
  • Hidden fields submit with the form and appear in the submission data alongside the customer’s message.
  • Describe this requirement to Fudge — it can build the complete implementation including hidden fields and JavaScript.

To capture UTM values in a Shopify form, add hidden inputs such as contact[utm_source] to the form, then run a short script that reads the URL with URLSearchParams and fills them in. The values arrive with the submission, so you can see which ad or email produced each inquiry.

How UTM parameters reach a Shopify form

UTM parameters are appended to URLs in your marketing links:

https://yourstore.com/pages/contact?utm_source=facebook&utm_medium=paid&utm_campaign=summer_sale

When someone lands on this URL, the UTM values exist in the browser’s URL bar. JavaScript can read them and store them so they travel with the form submission.

To add scripts like this to your theme, see how to add custom JavaScript in Shopify.

How to get UTM parameters from a URL with JavaScript

The modern, clean way to read URL parameters is URLSearchParams:

var params = new URLSearchParams(window.location.search)
var utmSource = params.get('utm_source') // "facebook"
var utmMedium = params.get('utm_medium') // "paid"
var utmCampaign = params.get('utm_campaign') // "summer_sale"
var utmContent = params.get('utm_content') // optional
var utmTerm = params.get('utm_term') // optional (for paid search)

If there’s no UTM parameter in the URL, params.get() returns null. Handle this gracefully by using empty string fallbacks.


Adding hidden UTM fields to a Shopify form

Step 1 - Add hidden fields to your form HTML.

In your theme’s contact form (typically in sections/contact-form.liquid or the contact page template), add hidden input fields inside the form:

<input type="hidden" id="utm-source" name="contact[utm_source]" value="" />
<input type="hidden" id="utm-medium" name="contact[utm_medium]" value="" />
<input type="hidden" id="utm-campaign" name="contact[utm_campaign]" value="" />
<input type="hidden" id="utm-content" name="contact[utm_content]" value="" />

On a product form, use name="properties[UTM Source]" to save it as a line item property. For custom forms or apps, use whatever naming convention your form system expects.

Step 2 - Read UTM values and populate the fields with JavaScript.

Add this script after your form (or in theme.liquid before </body>):

<script>
    ;(function () {
        var params = new URLSearchParams(window.location.search)
        var utmFields = {
            utm_source: 'utm-source',
            utm_medium: 'utm-medium',
            utm_campaign: 'utm-campaign',
            utm_content: 'utm-content',
        }

        Object.keys(utmFields).forEach(function (param) {
            var value = params.get(param)
            var field = document.getElementById(utmFields[param])
            if (value && field) {
                field.value = value
            }
        })
    })()
</script>

Step 3 - Test. Open your contact page with UTM parameters in the URL: https://yourstore.com/pages/contact?utm_source=test&utm_campaign=test_campaign

Submit the form and check the email notification — the UTM values should appear in the submission.

To build the form itself, see how to add a custom contact form in Shopify.


Persisting UTMs across multiple pages

A common problem: a visitor clicks your ad (UTMs are on the landing page URL), browses a few product pages, then visits the contact page directly — which has no UTMs in the URL. By the time they reach the form, the UTM values are gone.

Solution: store UTMs in sessionStorage (or localStorage) on first visit.

;(function () {
    var params = new URLSearchParams(window.location.search)
    var utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']

    // Store UTMs on first page load if present
    utmParams.forEach(function (param) {
        var value = params.get(param)
        if (value) {
            sessionStorage.setItem(param, value)
        }
    })

    // Populate form fields from storage (fallback from URL)
    function populateField(paramName, fieldId) {
        var value = params.get(paramName) || sessionStorage.getItem(paramName) || ''
        var field = document.getElementById(fieldId)
        if (field) field.value = value
    }

    populateField('utm_source', 'utm-source')
    populateField('utm_medium', 'utm-medium')
    populateField('utm_campaign', 'utm-campaign')
    populateField('utm_content', 'utm-content')
})()

sessionStorage persists values within a browser session (until the tab is closed). localStorage persists across sessions — more powerful, but also picks up UTMs from weeks-old visits, which may not be what you want.

Build a Shopify form with UTM tracking by describing it to Fudge.
Start free trial

UTM capture with form apps

Most dedicated form tools (Typeform, JotForm, Hulk Form Builder) have built-in UTM tracking:

Typeform: In the form settings, go to Hidden Fields → add UTM parameters. Typeform automatically reads these from the URL and attaches them to submissions.

Jotform: Prefill fields from URL parameters — add a field, go to Properties → Prefill → From URL Parameter.

These built-in options are simpler than custom JavaScript and worth using if you’re already using these tools.

To measure results, see how to add tracking scripts to Shopify.


What to do with UTM data in form submissions

Email routing. Send paid media leads to your sales team, organic leads to your content team.

CRM attribution. When the form submission enters your CRM (via Zapier, HubSpot integration, etc.), the UTM values travel with it. You can filter deals by source and see which campaigns generate the highest-value customers.

ROI reporting. If you know a wholesale customer came from a specific LinkedIn campaign, you can attribute their lifetime value back to that campaign — far more accurate than last-click analytics.

To see which campaigns lead to orders, see how to track conversions in Shopify.


FAQ

What's the difference between UTM tracking and Shopify's built-in attribution?

Shopify's marketing reports already read UTMs on orders. Capturing UTMs in form fields extends that to non-order events like contact and wholesale inquiries.

Will UTM parameters affect my Shopify SEO?

No. Search engines treat URLs with UTM parameters as the same page as the canonical URL (Shopify's canonical tags handle this automatically). UTMs are query string parameters that don't affect rankings or create duplicate content as long as canonicals are in place.

Can I capture UTMs from email links automatically?

Yes - if your email platform supports it (Klaviyo, Mailchimp, Omnisend all do). Configure the platform to append UTM parameters to all outgoing email links automatically. The UTM values then flow through your form capture exactly as they would from any other source.

How long should UTM values persist for a visitor?

For form-fill attribution, sessionStorage (until tab closes) is usually right. For longer-term attribution where someone might return weeks later to convert, localStorage with a 30-90 day expiry. Past 90 days, the UTM signal is usually noise rather than actionable attribution.

Should I store UTMs in customer notes when they sign up?

Yes if it's useful for sales follow-up. Add the same UTM-capture pattern to your account creation form, and store the values in the customer note (customer[note][utm_source]). Describe the setup to Fudge ("on every form, capture UTM source/medium/campaign from the URL and save them in the customer note") and it drafts the hidden fields and JavaScript across your forms for you to review.

Jacques's signature
Build custom Shopify forms with full attribution tracking by describing them.

You might also be interested in

Jacques Blom
Jacques Blom
CTO at Fudge.