Bulk UTM Generator & Campaign URL Builder
Build hundreds of tagged campaign URLs at once from manual rows or a CSV, with encoding handled and duplicates flagged before they reach your ad account.
A bulk UTM generator builds tagged campaign URLs in batches instead of one at a time. Fill in rows by hand or upload a CSV with url, source, medium, campaign, term and content columns, and every row comes back as a finished tracking link — up to 5,000 in a single pass, exportable as a CSV you can hand to whoever is trafficking the campaign.
This is the part of campaign setup that never scales manually. Twelve creatives across four placements in three markets is 144 links, and hand-editing query strings at that volume produces typos nobody notices until the report is already wrong. The builder keeps any query parameters your landing pages already rely on, encodes values properly, and marks any row that would produce a URL identical to another.
Your links
| URL | Source | Medium | Campaign | Term | Content | |
|---|---|---|---|---|---|---|
Your tagged URLs appear here
Fill in the rows or upload a CSV, then hit Generate — every link gets its UTM parameters appended, with duplicates and broken URLs flagged for you.
Need more than a free tool? Ask Kestry Chat Agent about your campaign strategy, marketing questions and customer workflows.
What Is a UTM Builder?
A UTM builder appends campaign tracking parameters to a destination URL so your analytics platform can tell where a visitor came from. You supply the landing page and the campaign details; the builder assembles a correctly formatted query string.
https://example.com/pricing ?utm_source=newsletter &utm_medium=email &utm_campaign=summer-sale &utm_content=cta-button
Single-URL builders are fine for a one-off link. They stop being useful the moment a campaign has more than one placement, because the work is no longer building a URL — it is building a consistent set of URLs where only one field changes at a time. That is a table problem, not a form problem, which is why this tool takes rows.
Three fields are mandatory in every row: source, medium and campaign. A row missing any of them is returned as an error rather than silently generating a half-tagged link, because a link with two of the three parameters is usually worse than an untagged one — it looks tracked in a spreadsheet and reports as unassigned traffic.
Why Use Bulk UTM Generation?
Volume is the obvious reason, but consistency is the one that actually changes your reporting. When links are built one at a time over three days by two people, small drifts creep in — paid-social on Monday, paidsocial on Wednesday, Paid_Social from the contractor. Generating the whole set in one pass from one table means every row inherits the same conventions.
- Launch sets — every ad variant, placement and market for one campaign, produced in a single pass with only the varying fields changed.
- Email sends — one campaign, one source, one medium, and a different utm_content for every link in the template so you can see which module drove the clicks.
- Affiliate and partner links — the same destination given to twenty partners with a different utm_source each, generated from a partner list you already maintain.
- Offline and QR campaigns — print, out-of-home and packaging links, where a broken URL cannot be fixed after it ships.
- Migrations — retagging an existing library of links to a new convention, exported as a CSV your team can diff against the old set.
There is a workflow benefit too. Because the input is a table, the source of truth can stay in the spreadsheet where the media plan already lives. You build the plan, export the columns, generate, and download a CSV with the original values and the generated URL side by side — which means the tagged link is traceable back to the plan row that produced it.
UTM Parameter Guide
The columns in the builder map directly onto the five standard parameters. Source, medium and campaign are required; term and content are written only when you supply a value, so blank optional cells never produce an empty parameter.
| Channel | utm_source | utm_medium | Typical utm_content |
|---|---|---|---|
| Meta paid ads | paid-social | carousel-v1 | |
| Google Search ads | cpc | sitelink-pricing | |
| LinkedIn sponsored | paid-social | single-image-b | |
| Newsletter | newsletter | header-cta | |
| Lifecycle email | klaviyo | abandoned-cart-2 | |
| Organic social post | social | bio-link | |
| Affiliate partner | partnername | affiliate | review-page |
| Printed QR code | packaging | qr | box-insert |
The values you put in a bulk run are worth more thought than the ones you type into a single-link form, because a convention mistake replicated across 500 rows is a genuinely expensive thing to unwind. Decide the medium vocabulary and the separator before you generate, not after.
The CSV Workflow
Switch to CSV upload when your links already live in a media plan or trafficking sheet. The parser expects a header row followed by data rows, and matches headers case-insensitively after trimming — so URL, Url and url are all accepted, and a stray trailing space will not break the import.
| Column | Required | What goes in it |
|---|---|---|
| url | Yes | The destination page, with or without an existing query string |
| source | Yes | Becomes utm_source |
| medium | Yes | Becomes utm_medium |
| campaign | Yes | Becomes utm_campaign |
| term | No | Becomes utm_term; skipped entirely when blank |
| content | No | Becomes utm_content; skipped entirely when blank |
- Download the CSV template if you are starting from scratch — it ships with the correct headers and one example row.
- Fill in your rows in a spreadsheet, keeping one link per row and the header row intact.
- Export as a plain .csv. The upload accepts files up to 2 MB; larger media plans should be split into batches.
- Upload the file. Missing required columns are named explicitly in the error rather than failing silently.
- Generate. The results table shows the first 200 rows on screen; the full set is always in the download.
- Download the results CSV, which pairs every original input value with its generated_url and a status of ok, duplicate, or the specific error message for that row.
Extra columns in your file are ignored rather than rejected, so you can upload a working media plan without stripping the budget, owner and flight-date columns first. Only the six recognised headers are read.
Encoding and Existing Query Parameters
Landing pages frequently carry query parameters that do real work — a variant flag, a language selector, an internal navigation reference. The builder keeps them. If your destination is https://example.com/pricing?ref=nav, the generated link is:
https://example.com/pricing?ref=nav&utm_source=newsletter&utm_medium=email&utm_campaign=summer-sale
The one exception is a utm_ parameter already present on the input URL. Those are replaced by the values from your row rather than duplicated, so re-running an already-tagged link through the builder retags it cleanly instead of producing a URL with utm_source twice — which would be an error in any validator and ambiguous to every analytics platform.
Why spaces become %20
Every value is percent-encoded as it is written into the query string, because a raw space is not legal in a URL. A campaign entered as Summer Sale is emitted as summer%20sale rather than being silently rejected or, worse, cutting the link short at the space when it is pasted into an email client.
| You enter | The URL contains | Reads back as |
|---|---|---|
| summer sale | summer%20sale | summer sale |
| b2b & enterprise | b2b%20%26%20enterprise | b2b & enterprise |
| 50% off | 50%25%20off | 50% off |
| cafe-menu | cafe-menu | cafe-menu |
A URL missing its scheme is treated as https. Fragments are preserved, so a link to https://example.com/faq#shipping keeps the anchor with the tracking parameters placed before it, where browsers expect them.
Duplicate Detection
After generating, every result is compared against the ones before it. Any row producing a URL byte-for-byte identical to an earlier row is flagged as a duplicate in the results table and marked duplicate in the exported CSV. The link is still generated — you decide whether it is a mistake.
Duplicates in a bulk run almost always mean one of three things:
- A row was copied down in the spreadsheet and a field that should have changed did not — usually utm_content across creative variants.
- Two genuinely different placements were given the same tags, so their performance will be pooled and you will never be able to separate them.
- The same link legitimately appears twice because it is going to two different destinations that need no distinction — in which case the flag is noise and you can ignore it.
Rows that fail outright are handled separately from duplicates. An invalid URL or a missing required field produces a row-level error message in the table and in the status column of the export, so a batch never fails as a whole because of one bad row.
Campaign Tracking Best Practices
- Write the convention down before the first bulk run. A documented list of approved sources and mediums is what keeps batch three consistent with batch one.
- Lowercase every value and use one separator throughout. Mixed case and mixed separators are the two most common causes of a fragmented campaign report.
- Keep utm_campaign aligned with the campaign name in the ad platform, so platform spend and analytics sessions join on a shared key.
- Vary one dimension per column. Creative in utm_content, audience or keyword in utm_term, and everything else held constant across the batch.
- Validate a sample of the output before trafficking. Ten links checked properly catch nearly every convention error in the batch.
- Click-test at least one generated link end to end, especially if your site redirects — some redirect rules drop query strings and no amount of correct tagging survives that.
- Keep the results CSV with the campaign brief. When somebody asks in six months what utm_content=hero-b referred to, that file is the only answer.
Finally, avoid tagging internal links. UTM parameters on a link between two pages of your own site restart the session in most analytics tools and overwrite the original acquisition source, so an internal banner tagged for convenience quietly rewrites the attribution of the campaign that brought the visitor in.