Table of Contents
Track UTM Parameters in Sitecore Forms
Are you using Sitecore and need to capture UTM parameters like utm_source
and utm_campaign
for analytics? In this post, I’ll walk through a clean, practical way to track utm parameters in Sitecore Forms without modifying Sitecore’s pipeline or relying on any heavy customisation.
The Basics: What Are UTMs?
Urchin Tracking Module (UTM) parameters are commonly used to track how users arrive on your site. But if you don’t capture them before a form is submitted, that valuable marketing data can disappear without a trace — something we want to avoid at all costs!
Here are some UTM parameters you may already be familiar with, along with how each is typically used:
utm_campaign
— Identifies the specific campaign that drove traffic to your site (e.g.big_sale
,black_friday
, ornewsletter_march
). Useful for tying traffic to a particular promotion or initiative.utm_content
— Distinguishes variations of the same ad or link. You might use this to A/B test CTA buttons (cta_button_red
,cta_button_blue
) or track different placements (sidebar_link
,footer_link
).utm_medium
— Describes the marketing channel. Common examples includeemail
,cpc
,social
, oraffiliate
. It helps group traffic by broad type.utm_source
— Specifies where the traffic came from, usually a platform or referrer (e.g.google
,facebook
,newsletter
,linkedin
).utm_term
— Captures search terms in paid search campaigns. For example, if someone clicked your ad after searching for “software engineer”, this could be set tosoftware+engineer
.utm_<custom>
— You can add your own custom UTM parameters to track any other context or segmentation relevant to your team. Just make sure your analytics tool or backend understands and logs it properly (e.g.utm_region=apac
,utm_version=v2
).
Now we’re familiar with what UTMs are and how they’re used, let’s look at how to implement this tracking in Sitecore Forms.
Step 1: Add Hidden UTM Fields in Sitecore
To enable UTM tracking in a specific form:
- Open the form in Sitecore Forms Editor.
- Add a Hidden field.
- Name it to match a UTM parameter you want to capture (e.g.,
utm_source
,utm_campaign
, etc). - Repeat the above step for as many standard or custom utms as you need.
- Publish the form.
Step 2: Capture and Apply UTM Parameters with JavaScript
We’re going to capture any UTM variables passed to the form using JavaScript. They’ll be stored locally using the browser’s session storage.
Take a look at this self-contained JavaScript snippet you can drop onto any page with a Sitecore form:
document.addEventListener('DOMContentLoaded', () => {
const formElement = document.querySelector('.sitecore-form form');
if (!formElement) return;
const urlParams = new URLSearchParams(window.location.search);
// Store any utm_<something> parameters
urlParams.forEach((value, key) => {
if (key.startsWith('utm_')) {
sessionStorage.setItem(key, value);
}
});
// Populate form hidden fields with any stored UTM params
Object.keys(sessionStorage).forEach((key) => {
if (key.startsWith('utm_')) {
const storedValue = sessionStorage.getItem(key);
const input = formElement.querySelector(`input[data-sc-field-name="${key}"]`);
if (input) input.value = storedValue;
}
});
// Clear UTM data on form submission
formElement.addEventListener('submit', () => {
Object.keys(sessionStorage).forEach((key) => {
if (key.startsWith('utm_')) {
sessionStorage.removeItem(key);
}
});
});
});
You can place this script in a layout file, partial view, or inline on a specific page—wherever your Sitecore form is rendered. Just make sure it loads after the form HTML.
Here’s what the form does:
- Detects
utm_
parameters in the query string. - Stores them in
sessionStorage
for the duration of the user’s session. - Fills in hidden fields when the form loads.
- Clears the data after submission.
Step 3: Working Example – Try it Yourself
Want to see it in action? Here’s a complete example you can try locally. Save the following HTML as utms.html
and open it in your browser. Then add some UTM parameters to the URL and watch them flow through to the form:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>UTM Test Form</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { font-family: sans-serif; padding: 2rem; max-width: 600px; margin: auto; }
label { display: block; margin-top: 1rem; }
input[type="text"], input[type="hidden"] { width: 100%; padding: 0.5rem; margin-top: 0.25rem; }
button { margin-top: 1.5rem; padding: 0.75rem 1.5rem; }
</style>
</head>
<body>
<h1>Sitecore UTM Parameter Test</h1>
<p>Try appending <code>?utm_source=test&utm_campaign=my_campaign</code> to the URL and reload the page.</p>
<div class="sitecore-form">
<form>
<label>
Name:
<input type="text" name="name" required>
</label>
<!-- Hidden fields for UTM parameters -->
<input type="hidden" data-sc-field-name="utm_source" name="utm_source">
<input type="hidden" data-sc-field-name="utm_medium" name="utm_medium">
<input type="hidden" data-sc-field-name="utm_campaign" name="utm_campaign">
<input type="hidden" data-sc-field-name="utm_term" name="utm_term">
<input type="hidden" data-sc-field-name="utm_content" name="utm_content">
<!-- Optional: example for custom UTM -->
<input type="hidden" data-sc-field-name="utm_custom" name="utm_custom">
<button type="submit">Submit</button>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const formElement = document.querySelector('.sitecore-form form');
if (!formElement) return;
const urlParams = new URLSearchParams(window.location.search);
// Store any utm_<something> parameters
urlParams.forEach((value, key) => {
if (key.startsWith('utm_')) {
sessionStorage.setItem(key, value);
}
});
// Populate form hidden fields with any stored UTM params
Object.keys(sessionStorage).forEach((key) => {
if (key.startsWith('utm_')) {
const storedValue = sessionStorage.getItem(key);
const input = formElement.querySelector(`input[data-sc-field-name="${key}"]`);
if (input) input.value = storedValue;
}
});
// Clear UTM data on form submission
formElement.addEventListener('submit', () => {
Object.keys(sessionStorage).forEach((key) => {
if (key.startsWith('utm_')) {
sessionStorage.removeItem(key);
}
});
alert('Form submitted. UTM data cleared from sessionStorage.');
});
});
</script>
</body>
</html>
Once you’ve saved and opened it, append some parameters to the query string and hit enter:
?utm_campaign=summer_sale&utm_custom=hello&utm_extra=world&another_variable=noaction
Once the page loads again, open dev tools and take a look at your local session storage. I’m using Chrome here, but you’ll find similar tooling in most modern browsers:

You can see in the screenshot above that utm
variables have been saved to session storage for use in the form. Note that the extra variable called another_variable
with the value noaction
was not stored because we are restricting by name in the JavaScript.
Also note that the hidden fields in the form have also been populated, but the utm_extra
that we don’t want to capture has been intentionally ignored:

This method doesn’t interfere with accessibility tools or input focus. Since we’re using hidden fields that Sitecore already expects, there’s no impact on screen readers or keyboard navigation.
Finally, type your name into the input field and submit the form. The hidden fields will have been posted to whichever destination you choose (whether that be an API or back-end code), and cleared from the session storage:

Note: Since this logic works entirely on the client side and doesn’t transmit sensitive data, it’s generally safe. However, always validate data server-side before using it in CRM or analytics integrations.
Evaluating This Approach
Here’s why this approach works well in Sitecore:
- Simple and lightweight — modern browser support, no extra dependencies.
- Works with AJAX and multi-step forms; persists across client-side transitions.
- Secure — relies only on expected hidden fields already defined in the CMS and isn’t blocked by Sitecore’s handling of dynamically-generated form fields.
- Empowers editors — campaign teams can launch UTM tracking without dev input.
Keep in mind…
If a user lands on one campaign page but completes a different form later in the session, UTM values may be misaligned. You can solve this by adding a form ID to the session key (e.g.,utm_source__form123
) or scoping UTM capture to specific forms.
Final Thoughts
If you’re working with Sitecore Forms and want a clean way to track UTM data, this method gives you all the flexibility without complicating your architecture. It’s quick to implement, safe with Sitecore’s form handling, and easily testable. Give the example a spin and see how it fits into your own tracking setup.
Have questions or your own tips for UTM tracking in Sitecore? Drop them in the comments — I’d love to see how others are approaching this.