UTM builder: build the link and see where it lands in GA4
Fill in the destination, the source and the campaign: the tool builds the link, normalizes the values without breaking your ad platform macros, predicts which GA4 channel group that click will land in, and keeps your taxonomy in this browser so it can warn you when you type the second version of the same name. Free, no signup, and nothing leaves your machine.
Advanced GA4 fields
Your link
- - parameters
- - characters in the URL
- - values normalized
What the link gets right (and what is missing)
- Destination URL is absolute and valid
- Source, medium and campaign filled in
- Values with no uppercase, accents or spaces
- No personal data in the link
- No leftover UTM on the destination URL
- GA4 recognizes the source and medium pair
- Link published outside your own site
- No clash with Google Ads auto-tagging
- URL within a safe length
- Source, medium and campaign hold different values
Warnings
Your saved links
Nothing saved yet. Save the first link and the tool starts warning you when you type a second version of the same name.
Everything runs in your browser: the link is not built on a server, no URL is visited, and the history stays on this device only, in local storage. The channel group is a prediction of the public GA4 rules using a reduced site list, not a lookup against your account.
A UTM builder is half an hour of code: take the fields, join them with ampersands, return the string. What almost none of them deliver is the part that decides whether the data will be usable: which category GA4 will file this link under and whether the name you just typed is the same one you used last month. Those two points are the work this page does. If your problem sits earlier and you are still wiring up measurement for an experiment, start with the GA4 and A/B testing guide; if it sits later and the question is how to credit revenue to the right channel, that is attributing revenue to the winner.
The builder is the easy half. Taxonomy is the expensive one.
No team ever lost money because it put an ampersand in the wrong place. Teams lose money because, six months later, the source report shows facebook, Facebook, fb and facebook.com splitting the same sessions across four rows, and because half the campaigns were tagged with a medium GA4 does not even recognize. The damage surfaces at budget time, which is precisely when nobody has the patience to reconstruct the reading by hand.
Both defects share one cause: UTMs get written by many people, at many moments, with nothing comparing today's value against yesterday's. That is why this tool keeps a local history. It is not there so you can reuse links, it is there as memory, and the division of labour goes like this: normalization kills case and accents before they can turn into a variant, and the history catches whatever survives normalized, which is the hard case. Save black-friday-2026 today and type black_friday_2026 or blackfriday2026 a month from now: the warning shows up before the link ships. With normalization off, the comparison covers case and accents too. Taxonomy consistency is not solved by a document in Notion, it is solved at the point where the name gets written.
How to use it
- Paste the full destination URL, starting at https. If it already carries UTMs from another campaign, the old ones are removed: a link with two utm_source values is read by the first one and the rest is noise.
- Pick a channel preset to fill source and medium with the usual convention, or type both yourself. The preset is a starting point, not a rule.
- Name the campaign after the initiative, not the creative. The specific piece belongs in utm_content, and that split is what lets you compare two ads inside the same push.
- Read the predicted channel group. If it says Unassigned, the problem is not cosmetic: that traffic will arrive with no category in the acquisition report.
- Clear whatever the checklist flags, copy the link and save it to the history. From the second saved link on, the tool starts comparing every new name against the ones you already used.
How it works: the nine parameters
UTM is not a Google standard: it came from Urchin, the tool acquired in 2005 that became Analytics, and it survived because it is only text in the URL. Any system that reads the address bar can interpret it. Today there are nine fields, three required and six optional:
The last three are GA4 additions and almost nobody fills them in, which is reasonable: they only pay off once you already have enough volume to segment by format or by tactic. They sit in the advanced block for completeness, not because every campaign needs them.
Normalization deserves its own paragraph because it holds an exception most builders get wrong. Turn the option on and every value loses its accents, goes lowercase and swaps spaces for the chosen separator. What must not be touched is the platform macro: Google's {keyword} and Meta's {{campaign.name}} get substituted at click time, and changing those braces breaks the whole substitution. So macros are masked before normalization and returned intact afterwards. Type Ads {keyword} US and you get ads-{keyword}-us: text normalized, braces preserved.
The rule that decides your acquisition report
Here is what separates this page from a string concatenator. GA4 does not store your utm_medium as a category. It runs the source and medium pair through a sequence of rules and stores the first group that matches. Order matters, because the first hit ends the search:
Two things fall out of that order, and both explain reports that look broken. First: the site list decides before the medium does. Tag a newsletter blast with utm_source equal to google and utm_medium equal to email and the result is not Email, it is Organic Search, because the search rule comes first and google sits in the search site list. Second: a medium that matches nothing becomes Unassigned. Values that read as perfectly descriptive to whoever wrote them, like offline, flyer, qr or partnership, appear in no rule and send the traffic to the nameless bucket.
That is why the printed QR code preset in this tool lands in Unassigned on purpose. It is not a bug: it is the real behavior, shown before you send five thousand flyers to the printer. If the QR needs to show up as an identifiable channel, the way out is to pick a medium GA4 recognizes and reserve utm_source for the material itself.
One note of honesty: Google's site list holds hundreds of entries and changes without announcement. The prediction here uses a reduced list covering the vehicles that actually show up. It gets the common case right and may diverge on a little known regional vehicle. Treat it as a prediction, not as a lookup against your account.
Worked example (reproduces the default result)
The values that load by default describe a Meta ad pointing at a pricing page, with one piece of dirt planted on purpose: the source was typed as Facebook, capital F, and the campaign as Black Friday 2026, with spaces. That is how it arrives from a real brief.
- With normalization on and the hyphen as separator, the source becomes
facebookand the campaign becomesblack-friday-2026. The normalized values counter reads 2. - The link settles at 131 characters, with four parameters:
?utm_source=facebook&utm_medium=paid-social&utm_campaign=black-friday-2026&utm_content=price-carousel. - Predicted channel group: Paid Social, because facebook sits in the social site list and paid-social matches the paid medium pattern. Change the medium to social, dropping the paid, and the same link turns into Organic Social.
- The checklist closes 10 out of 10, and a warning still shows up: paid medium with no utm_id. That is the field tying the click to imported cost, and without it the campaign shows in the report with no spend beside it.
Type anything into utm_id and the warning goes away. Now uncheck the external link box and watch: the checklist drops to 9 out of 10 and the internal link alert appears, which is the mistake that ruins the data without warning you anywhere.
How to read it, and where the tool misleads
The checklist measures the link, not the campaign. Ten out of ten on a bad ad is still a bad ad with a well written URL. What it guarantees is that when the result arrives, you will be able to read which channel it came from.
The second limit is auto-tagging. If your paid traffic comes from Google Ads with auto-tagging on, the gclid already carries campaign, group, keyword and cost, and it wins over manual UTM inside GA4. Tagging by hand on top adds no information and creates two slightly different counts of the same campaign. Manual tagging exists for what has no auto-tagging.
The third is that nobody guarantees the parameter arrives whole. Shorteners, misconfigured redirects, apps that open links in an embedded browser and platforms that rewrite URLs can all drop the query string. After publishing, open the link once and check the parameters are still in the address bar.
The fourth is the history. It lives in the local storage of this browser. Switch machines, clear site data or open a private window and it does not exist. To turn it into team taxonomy, use the spreadsheet button and keep the file where the whole team can see it.
From link to decision
Good tagging buys one thing: the ability to compare channels without arguing about where the visit came from. Once the tagging is clean, the bottleneck becomes what you do with the difference between them. The short path:
- Check that the event you call a conversion fires correctly, using the method in how to track A/B test events in GA4.
- Before declaring that one channel converts better than another, see how much traffic that difference needs in order not to be luck, with the sample size calculator.
- If the difference is in page conversion rather than in channel, the next step is the conversion rate calculator and a properly written hypothesis in the hypothesis generator.
Frequently asked questions
- Which UTM parameters are required?
- Three: utm_source, utm_medium and utm_campaign. The other six are optional and exist to add detail. The reason those three are required is not bureaucracy: GA4 builds the channel group out of the source and medium pair, and uses the campaign to group the effort. Miss any of the three and the visit either lands in Unassigned or gets read as direct traffic, which is the bucket that collects everything that failed to identify itself.
- Is UTM case sensitive?
- It is, and that is the most expensive mistake in the whole field. Facebook, facebook and FaceBook become three distinct sources in the report, each holding a slice of your sessions and your conversions. There is no easy retroactive fix: what was stored is what was sent, and merging afterwards means editing the report rather than the source. That is why normalization ships on in this tool, and why the history warns you when you type the second version of a name you already used.
- Should I put UTMs on Google Ads links?
- Usually not, because auto-tagging already handles it. With it on, Google appends a gclid to every click and GA4 reads campaign, ad group, keyword and cost from it, which is more information than any manual UTM carries. Tagging by hand on top of that adds nothing and can produce two different counts for the same campaign. Manual tagging is for what has no auto-tagging: newsletters, partners, organic posts, QR codes, email signatures.
- Can I put UTMs on internal links?
- No. It is the second most common mistake and the most destructive one, because it ruins the data without raising any error. Clicking a tagged internal link starts a new session and rewrites where the visitor came from: the person who arrived through your paid ad starts counting as if they came from a banner on your own homepage. The conversion goes to the wrong channel and the channel that paid for it gets no credit. To measure clicks on internal elements the right instrument is an event, not a UTM.
- What is the difference between utm_content and utm_term?
- utm_term holds the paid keyword and only makes sense on search. utm_content holds the creative or the placement, and exists to tell apart two pieces that point at the same page inside the same campaign: the carousel and the video, the top button and the footer link of an email. A rule of thumb: if you want to compare two versions of the same thing, that is utm_content. If you want to know which term somebody searched for, that is utm_term.
- What is utm_id for?
- It is the campaign identifier in the platform that spent the money, and it is what ties the click to cost imported into GA4. Without utm_id, the cost data import finds no matching row and the campaign shows up in the report with sessions and conversions but no spend beside them. Every time this tool detects a paid medium with that field empty it says so, because that is exactly where the return calculation stops adding up.
- Why did my utm_medium turn into Unassigned in GA4?
- Because GA4 does not store your utm_medium as a category: it runs the source and medium pair through a list of rules and stores whichever group survives. If your medium matches no rule, the result is Unassigned. That is what happens to creative values that felt obvious to whoever wrote them, like offline, qr, flyer, whatsapp-status or partnership. The tool shows the predicted group before you publish, which is while you can still change it.
- Can I put a customer email in a UTM?
- No, and this is the one rule on this page that is not a matter of style. Personal data in a URL parameter is forbidden by the Google Analytics terms and processes personal data with no legal basis under GDPR and similar laws, on top of leaking into server logs, referrers and any tool that reads the URL. If you need to tie a visit to a person, the path is an internal identifier with no external meaning, on the inside, not a readable string in the address bar.
Keep going
With the link tagged and the channel predicted, the next step is turning the gap between channels into a decision. Start with GA4 and A/B testing to close the measurement loop, see what changes in conversion work in CRO in the age of AI, and when you go compare two landing pages behind the same ad, start at what is A/B testing.