Build UTM campaign links
When one person types Newsletter and another types newsletter, one campaign splits into two rows of your report: fill in source, medium and campaign to get a correctly encoded tagged link, or paste an existing one to read its parts. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
consistent and parseable, free
Why hand-typed tags break your reports
UTM parameters, named after the Urchin Traffic Monitor, were adopted early as a simple way to tag a link with where a visitor came from, and their five parts, source, medium, campaign, term and content, have lasted across every major analytics tool. The convention only works if the values are written the same way every single time, and that is exactly what manual entry gets wrong. Someone writes Newsletter, someone else newsletter, and one campaign appears as separate rows, each with a fraction of the real traffic. Multiply that across dozens of campaigns and hundreds of shared links and the dashboard stops answering the question it was built for.
Building links and checking them before a launch
You fill in the base address and the campaign values, and the tool returns a properly encoded tagged link that keeps any parameter the address already had. You can also paste an existing tagged link and get its parts back one by one. That covers both sides of the job: generating a link for every scheduled social post or every link in a newsletter template, and auditing a batch of links from different contributors to catch inconsistent source or medium values before the campaign goes live. Partner programs use the same approach to give each affiliate a unique tagged link, so traffic is credited without relying on the partner to build it correctly.
Why five parameters became the industry standard
Urchin Traffic Monitor parameters predate the analytics platform most people associate them with today; they were adopted early on as a simple, vendor-agnostic way to tag a URL with where a visitor came from, and the five-parameter shape — source, medium, campaign, term, content — has stuck around across every major analytics tool since because it maps cleanly onto how marketers actually think about a campaign.
The convention only works, though, if the values going into it are applied the same way every single time, which is precisely the part that manual entry gets wrong.
What you can do with it
Automated campaign link generation
A social media scheduling tool builds a correctly tagged URL for every scheduled post so weekly reporting doesn't require manual link tagging.
Auditing links before a launch
A marketing ops team parses a batch of links submitted by different contributors to catch inconsistent source or medium values before a campaign goes live.
Email platform integration
An email sending tool tags every link in a newsletter template automatically so campaign performance rolls up correctly in analytics.
Affiliate and partner link tracking
A partner program generates a unique tagged URL per affiliate so each partner's traffic is attributed without relying on the partner to build the link correctly.
FAQ
Does it handle URL encoding automatically?
Yes, spaces and special characters in campaign values are encoded correctly so the resulting URL is valid in any browser or analytics tool.
Are the URLs I submit stored?
No, submitted and generated URLs are deleted after the retention window and are never used for training.
What are the five UTM parameters?
Source, medium, campaign, term and content. The first three are the core of every tagged link and the last two are optional. This five-part shape has lasted across every major analytics tool because it maps onto how marketers think about a campaign.
Can I read the parameters out of an existing link?
Yes. Choose the reading option and paste a tagged link to get each parameter back separately. It is a quick way to audit links from different people before a launch and catch inconsistent source or medium values.
What happens if my link already has parameters?
They stay. In the example, a link that already carries a ref value keeps it, and the source, medium and campaign tags are added after it, so nothing the page relies on is lost.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev/utm \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/landing"}'const res = await fetch("https://api.kit.forhosting.com/dev/utm", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"url": "https://example.com/landing"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/utm",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"url": "https://example.com/landing"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/utm", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"url":"https://example.com/landing"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"url":"https://example.com/landing"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/utm", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"url": "https://example.com/landing"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.utm",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Analytics dashboards fracture into a hundred near-duplicate campaign names the moment two people are allowed to type utm_source by hand. This endpoint builds tagged URLs from structured fields and parses existing links back into their parts, so every campaign shows up in reports exactly once.
The typo that splits your traffic report
Multiply that across dozens of campaigns and hundreds of links shared by different team members, and the dashboard stops answering the question it was built to answer. dev.utm removes the human typing step from the part of the process where consistency actually matters. Marketing teams rarely lose UTM discipline on purpose — someone writes 'Newsletter', someone else writes 'newsletter', a third person writes 'news_letter', and now a single campaign shows up as three separate rows in the analytics tool, each with a fraction of the real traffic.
Building and reading links through one endpoint
POST /dev/utm with a base URL and the campaign fields — source, medium, campaign name, and optionally term and content — to get back a properly encoded, tagged URL; or send an existing tagged URL to have it parsed back into its individual parameters. The call returns a task_id right away, and the result arrives by signed webhook or a signed link valid for 24 hours, so the same endpoint covers both generating new links for a campaign and auditing a batch of links someone else already created.
Where it removes friction from a marketing pipeline
A content calendar tool can generate a tagged link automatically the moment a social post is scheduled, an email platform can tag every outbound campaign link without asking a copywriter to remember the naming convention, and a link-shortener service can validate that inbound URLs follow house rules before they ever go live. Because it's billed per request with no minimum commitment, a team can route every outbound link through the endpoint as a matter of course rather than reserving UTM discipline for the campaigns someone remembers to tag by hand.
Technical questions
How do I build a UTM URL with the API?
POST the base URL and campaign fields to /dev/utm, keep the returned task_id, and collect the tagged URL by webhook or a signed link valid for 24 hours.
Is the UTM builder API free?
No, there is no free tier or trial; it costs $0.002 per request, and a failed request is never charged.
Can it parse an existing UTM link back into its parts?
Yes, send an already-tagged URL and the endpoint returns the individual source, medium, campaign, term and content values.
Does it enforce a naming convention?
It builds and parses standard UTM parameters consistently; if your team has house rules for naming, applying them through one endpoint is what keeps every link consistent.
Can I generate UTM links in bulk?
Yes, submit one async task per URL and collect each result by webhook, which suits generating links for an entire campaign calendar at once.
Is this endpoint live?
Yes, /dev/utm is live and accepting requests now.