# UTM Builder

Build UTM-tagged links that land in the right GA4 channel. This page is the builder: pass the values as query parameters and it answers with the tagged link, the GA4 channel it will be grouped under and anything that will break your reports. No key, no sign-up, nothing is stored.

## How to call it

GET `https://www.usenotra.com/utm-builder.md?url=example.com/pricing&source=newsletter&medium=email&campaign=spring-launch`

The same query on `https://www.usenotra.com/utm-builder` opens the builder with every field filled in, so you can hand a person a link to check before they publish. Requests to `https://www.usenotra.com/utm-builder` with `Accept: text/markdown` get this page.

Tag one campaign for several channels in one call:

GET `https://www.usenotra.com/utm-builder.md?url=example.com&campaign=spring-launch&channels=newsletter,linkedin,google-ads`

URL-encode the `url` value when it has its own `?`, `&` or `#`, otherwise those parts are read as builder parameters.

Errors keep the link out of the result and come back with status 422. Warnings still return a link.

## Parameters

| Query key | UTM parameter | Need | What it is |
| --- | --- | --- | --- |
| `url` | (destination) | Required | The page to send people to. `https://` is added when missing. Existing query parameters and the `#fragment` are kept, existing `utm_` parameters are replaced. |
| `source` | `utm_source` | Required | Where the click comes from: a site, platform or list. Examples: google, linkedin, newsletter. |
| `medium` | `utm_medium` | Recommended | The type of traffic. GA4 groups channels mostly by this value. Examples: cpc, email, social, paid-social, affiliate. |
| `campaign` | `utm_campaign` | Recommended | The campaign, launch or promotion the link belongs to. Keep it the same across every channel so you can compare them. |
| `id` | `utm_id` | Optional | A stable ID for the campaign. GA4 needs it to join imported cost data to sessions. |
| `term` | `utm_term` | Optional | The paid keyword or audience that triggered the ad. |
| `content` | `utm_content` | Optional | Tells apart links that share everything else, such as two buttons in one email or two ad variants. |
| `platform` | `utm_source_platform` | Optional | The platform that runs the campaign, such as a buying tool or ad manager. |
| `format` | `utm_creative_format` | Optional | The type of creative, such as display, native or video. |
| `tactic` | `utm_marketing_tactic` | Optional | The targeting applied to the campaign, such as remarketing or prospecting. |
| `channels` | (several links) | Optional | Comma-separated preset IDs from the table below. Returns one tagged link per channel, sharing campaign, ID and the other values. |
| `clean` | (behaviour) | Optional | `true` by default: lowercase values and turn spaces into dashes. Placeholders in `{braces}` are left alone. Send `false` to keep values as typed. |

## Channel presets

| Preset ID | Channel | utm_source | utm_medium | Extras | GA4 channel |
| --- | --- | --- | --- | --- | --- |
| `newsletter` | Newsletter | newsletter | email | - | Email |
| `linkedin` | LinkedIn post | linkedin | social | - | Organic Social |
| `x` | X post | x | social | - | Organic Social |
| `reddit` | Reddit post | reddit | social | - | Organic Social |
| `youtube` | YouTube video | youtube | video | - | Organic Video |
| `google-ads` | Google Ads | google | cpc | utm_term=`{keyword}`, utm_content=`{creative}` | Paid Search |
| `meta-ads` | Meta Ads | facebook | paid-social | utm_term=`{{adset.name}}`, utm_content=`{{ad.name}}` | Paid Social |
| `linkedin-ads` | LinkedIn Ads | linkedin | paid-social | - | Paid Social |
| `bing-ads` | Microsoft Ads | bing | cpc | - | Paid Search |
| `partner` | Partner or affiliate | partner | affiliate | - | Affiliates |
| `podcast` | Podcast | podcast | audio | - | Audio |
| `sms` | SMS | sms | sms | - | SMS |

- Google Ads: {keyword} and {creative} are ValueTrack parameters Google Ads fills in at click time.
- Meta Ads: {{adset.name}} and {{ad.name}} are dynamic parameters Meta fills in at click time.

## How GA4 assigns a channel

GA4 checks these rules from top to bottom and stops at the first match. Values are compared in lowercase, so clean values give stable results.

| Order | Channel | Rule |
| --- | --- | --- |
| 1 | Direct | Source is (direct) and medium is (none) or (not set). |
| 2 | Cross-network | Campaign name contains cross-network. |
| 3 | Paid Shopping | Source is a shopping site or campaign name contains shop or shopping, and medium is paid. |
| 4 | Paid Search | Source is a search engine and medium is paid. |
| 5 | Paid Social | Source is a social network and medium is paid. |
| 6 | Paid Video | Source is a video site and medium is paid. |
| 7 | Display | Medium is display, banner, expandable, interstitial or cpm. |
| 8 | Paid Other | Medium is paid, source is anything else. |
| 9 | Organic Shopping | Source is a shopping site or campaign name contains shop or shopping. |
| 10 | Organic Social | Source is a social network, or medium is social, social-network, social-media, sm, social network or social media. |
| 11 | Organic Video | Source is a video site, or medium contains video. |
| 12 | Organic Search | Source is a search engine, or medium is organic. |
| 13 | Referral | Medium is referral, app or link. |
| 14 | Email | Source or medium is email, e-mail, e_mail or e mail. |
| 15 | Affiliates | Medium is affiliate. |
| 16 | Audio | Medium is audio. |
| 17 | SMS | Source or medium is sms. |
| 18 | Mobile Push Notifications | Medium ends with push or contains mobile or notification, or source is firebase. |
| 19 | Unassigned | Nothing above matched. |

Paid means the medium matches cp (cpc, cpm, cpv and so on), ppc, retargeting or starts with paid.

Search engine, social network, video and shopping sources come from lists Google maintains. This builder checks the common entries, so a niche source may land in a different channel than predicted.

## Naming rules that keep reports clean

- Use lowercase everywhere. `Email`, `email` and `EMAIL` are three rows in GA4.
- Use dashes instead of spaces. Spaces turn into `%20` or `+` and are easy to mistype.
- Keep the source the site or list, and the medium the type of traffic. `source=newsletter&medium=email`, not the other way round.
- Reuse one campaign name across every channel of a push and tell links apart with `utm_content`.
- Never tag internal links between pages of your own site. It starts a new session and overwrites where the visitor really came from.
- Add `utm_id` when you import cost data into GA4. It is the key the import joins on.
