Free tool Bulk UTM builder: a whole campaign sheet at once
Copy the rows from your campaign plan, paste them here and get one tagged link per row. Values are cleaned the same way every time, so the email team and the ads team end up with matching sources and mediums.
- CSV or TSV, up to 2,000 rows
- Download as CSV
- Runs locally
Build UTM links from a table
The sample is a spring sale plan with a header row. Columns can be in any order; without a header, use url, source, medium, campaign, term, content, or leave out the URL and fill in the base URL.
Used for rows without a URL and for rows that hold only a path such as /pricing.
Paste from Excel or Google Sheets (tab-separated) or a CSV. Header names such as url, landing page, utm_source or source are recognised.
Rows
7
Links built
7
Rows with a valid URL and a utm_source.
Rows with errors
0
No link was built for these rows.
Tagged links
GA4 channel is the default channel group GA4 would assign from the final source, medium and campaign.
| Line | Tagged URL | utm_source | utm_medium | utm_campaign | GA4 channel | Status |
|---|---|---|---|---|---|---|
| 2 | https://shop.example.com/spring?utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale&utm_content=hero_button | newsletter | email | spring_sale | OK | |
| 3 | https://shop.example.com/spring?utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale&utm_content=footer_link | newsletter | email | spring_sale | OK | |
| 4 | https://shop.example.com/spring?ref=partner&utm_source=partner_blog&utm_medium=referral&utm_campaign=spring_sale | partner_blog | referral | spring_sale | Referral | OK |
| 5 | https://shop.example.com/pricing?utm_source=linkedin&utm_medium=social&utm_campaign=spring_sale&utm_content=carousel | linkedin | social | spring_sale | Organic Social | OK |
| 6 | https://shop.example.com/spring?utm_source=facebook&utm_medium=paid_social&utm_campaign=spring_sale&utm_content=video_ad#faq | facebook | paid_social | spring_sale | Paid Social | OK |
| 7 | https://shop.example.com/spring?utm_source=google&utm_medium=cpc&utm_campaign=spring_sale | google | cpc | spring_sale | Paid Search | OK |
| 8 | https://shop.example.com/spring?utm_source=podcast&utm_medium=sponsorship&utm_campaign=spring_sale | podcast | sponsorship | spring_sale | Unassigned | Check |
Checks
- Note3 values were changed by the options above (lowercase, spaces). The table and CSV show the final values.
- WarningLine 8GA4 has no default channel for medium "sponsorship", so this traffic lands in Unassigned. Use a standard medium such as email, social, cpc, referral or affiliate.
row,landing_page,utm_source,utm_medium,utm_campaign,utm_term,utm_content,tagged_url,ga4_channel,status
2,https://shop.example.com/spring,newsletter,email,spring_sale,,hero_button,https://shop.example.com/spring?utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale&utm_content=hero_button,email,ok
3,https://shop.example.com/spring,newsletter,email,spring_sale,,footer_link,https://shop.example.com/spring?utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale&utm_content=footer_link,email,ok
4,https://shop.example.com/spring?ref=partner,partner_blog,referral,spring_sale,,,https://shop.example.com/spring?ref=partner&utm_source=partner_blog&utm_medium=referral&utm_campaign=spring_sale,referral,ok
5,https://shop.example.com/pricing,linkedin,social,spring_sale,,carousel,https://shop.example.com/pricing?utm_source=linkedin&utm_medium=social&utm_campaign=spring_sale&utm_content=carousel,organic_social,ok
6,https://shop.example.com/spring#faq,facebook,paid_social,spring_sale,,video_ad,https://shop.example.com/spring?utm_source=facebook&utm_medium=paid_social&utm_campaign=spring_sale&utm_content=video_ad#faq,paid_social,ok
7,https://shop.example.com/spring,google,cpc,spring_sale,,,https://shop.example.com/spring?utm_source=google&utm_medium=cpc&utm_campaign=spring_sale,paid_search,ok
8,https://shop.example.com/spring,podcast,sponsorship,spring_sale,,,https://shop.example.com/spring?utm_source=podcast&utm_medium=sponsorship&utm_campaign=spring_sale,unassigned,warningOne row per input row, with the landing page, each UTM value, the tagged URL, the GA4 channel and a status.
Version v1.0Updated Update history
What comes back for each row
Every input row produces one output row, in the same order, so the CSV can be pasted back next to your plan.
Tagged URL
The landing page with utm_source, utm_medium, utm_campaign and, if given, utm_term and utm_content added to the query string. Existing parameters keep their original text, and any #anchor stays at the end where it belongs.
Status
Not built means the row has no usable URL or no source. Check means a link was built but something will hurt the data: an empty medium or campaign, a medium GA4 does not recognise, or the same final URL as an earlier row.
GA4 channel
Where GA4's default channel group would put the visit, worked out from the final values. If a row says Unassigned or Paid Other, change the medium or source before the links go out. The rules are listed on the UTM checker page.
The CSV
Columns: row, landing_page, utm_source, utm_medium, utm_campaign, utm_term, utm_content, tagged_url, ga4_channel, status. It is UTF-8 with a byte-order mark so Excel opens accented and Chinese text correctly, and cells that start with =, +, - or @ are prefixed with an apostrophe so a spreadsheet does not run them as formulas.
The row number is the line in what you pasted, so line 1 is the header when there is one.
From campaign plan to links in three steps
Keep the plan in a spreadsheet; use this page as the step that turns it into links.
-
1
Copy the rows
Select the URL, source, medium, campaign (and optionally term and content) columns in Excel or Google Sheets, header included, and paste. Or set a base URL and paste only the UTM columns.
-
2
Pick the conventions
Lowercase and underscores are the safe default. Decide whether existing UTM values in the URLs should be replaced, which is what you want when re-tagging old links.
-
3
Fix, then download
Clear the errors and warnings, then download the CSV or copy it back into the sheet. Run the final links through the UTM checker if they will be edited by hand later.
How rows are read and links are built
The same input always gives the same output, so two people running the same sheet get identical links.
- The separator is whichever of tab, comma or semicolon appears most in the first line; quoted cells may contain commas and line breaks
- Values are trimmed; with the defaults they are lowercased and runs of spaces become one underscore
- Parameter values are percent-encoded (RFC 3986), so
&or#in a value cannot break the URL
| Input | How it is read |
|---|---|
| First row has 2+ known names | Header row. Known: url, link, landing page, website, source, medium, campaign, name, term, keyword, content, with or without utm_ |
| No header, first cell looks like a URL | Columns are url, source, medium, campaign, term, content |
| No header, base URL set | Columns are source, medium, campaign, term, content; every row uses the base URL |
URL cell is a path like /pricing | Joined to the base URL |
URL already has utm_* | Replaced (default) or kept, depending on the overwrite option |
| Empty utm cell | Parameter left out; with overwrite on, an existing one is removed |
The spring sale sheet
Seven rows from the sample, three of them typed by someone who prefers capitals. With the default options:
| Line | Input | Output | Note |
|---|---|---|---|
| 3 | Newsletter, Email, Spring Sale | …?utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale&utm_content=footer_link | Matches line 2 apart from content |
| 4 | URL with ?ref=partner | …/spring?ref=partner&utm_source=partner_blog… | Existing parameter kept first |
| 5 | /pricing | https://shop.example.com/pricing?utm_source=linkedin… | Path joined to the base URL |
| 6 | URL with #faq | …&utm_content=video_ad#faq | Anchor moved after the query |
| 8 | Medium sponsorship | Link built | GA4: Unassigned; use referral or cpc |
Without lowercase, line 3 would produce a second source (Newsletter), a second medium (Email) and a second campaign (Spring Sale) in every report.
What goes wrong with UTM spreadsheets
A sheet scales tagging; it also scales the mistakes in it.
Concatenating with a formula
=A2&"?utm_source="&B2 breaks as soon as a URL already has a ? or a #, and does not encode spaces or ampersands. Let a builder join and encode the parts.
No agreed vocabulary
Two people fill in the sheet; one writes Facebook, the other fb. Keep a short list of allowed sources and mediums in a second tab and use data validation.
Same link for every placement
When the header, footer and P.S. links of an email are identical, you cannot tell which one worked. Give each its own utm_content.
Tagged links become campaign reports
TapCub reads the UTM parameters on the landing page, assigns the visit to a channel and keeps it on the visitor, so later conversions still count for the campaign.
Campaign breakdowns
Campaign, source, medium and content each get a breakdown with sessions, conversions and conversion rate.
Learn moreFirst and last touch
Compare which campaigns introduce customers and which ones close them.
Learn moreChannel ROI
Import spend per channel and read return next to the conversions it bought.
Learn moreBulk UTM builder questions
Still have a question?
Chat with the team behind TapCub — we usually reply within a few hours on business days.
How do I create UTM links in bulk?
Put one link per row in a spreadsheet with columns for URL, source, medium and campaign, copy the rows including the header, and paste them into the builder. Each row comes back as a tagged URL, and the whole set downloads as a CSV you can paste back into the sheet.
What columns does the CSV need?
At least a source for every row, plus a URL column or a base URL. Medium and campaign are strongly recommended; term and content are optional. Column order does not matter when there is a header; without one, the order is url, source, medium, campaign, term, content.
Can I paste straight from Excel or Google Sheets?
Yes. Copying cells from a spreadsheet gives tab-separated text, which is detected automatically. CSV files opened in a text editor work too, including quoted cells with commas inside.
Should UTM values be lowercase?
Yes, as a rule. Analytics reports are case-sensitive, so Email and email become two mediums. GA4's channel rules ignore case, which hides the problem until you look at source and medium tables. The lowercase option is on by default.
Can UTM values contain spaces, accents or non-Latin text?
They can, because the builder percent-encodes every value, but it is rarely worth it. é becomes %C3%A9 and a Chinese word becomes a long string of escapes, which makes links long in SMS and QR codes and easy to retype wrongly. Use short lowercase ASCII for source, medium and campaign; put descriptive text in utm_content or utm_term if you need it.
What happens to parameters already in my URLs?
Non-UTM parameters such as ref or gclid are kept as they are unless you turn off "keep existing query parameters". UTM parameters already in the URL are replaced by the sheet's values, or kept if you turn off overwrite.
Is there a row limit?
2,000 rows per run, which keeps the page responsive on phones. Larger sheets can be pasted in batches.
Does my campaign sheet get uploaded?
No. Parsing and building happen in your browser, nothing is sent to TapCub, and there is no share link. The CSV is generated on your device.
Update history
New features, fixes and data refreshes for this tool, newest first.
-
· v1.0
LaunchedFirst release.
Data this tool relies on
- GA4 default channel group source lists — checked 2026-11-09, reviewed every 6 months (next review by 2027-05-09)
Missing something or found an error? Tell us — requests that come up often go into the next update. All tool updates
Watch the campaign come in
Once the links are live, TapCub shows each campaign's visits and conversions as they arrive, broken down by source, medium and content.