# UTM campaign tracking

> Track UTM campaigns with visitors, conversions, revenue, cost, CPA and ROAS, build tagged links with the UTM builder, and clean up near-duplicate UTM values.

## Campaign report

**Campaigns** rolls UTM-tagged traffic up by campaign, then source and
medium, with visitors, visits, conversions, conversion rate, revenue and,
when you add costs, **cost**, **CPA** (cost per conversion) and **ROAS**
(revenue ÷ cost).

UTM values come from the landing page of each visit. Values are compared
as sent, so `Facebook` and `facebook` are reported as different values
(see [UTM hygiene](/docs/features/campaigns#utm-hygiene) below).

## Costs

In **Campaigns → Costs**, add spend per campaign per month by hand, or
upload a CSV with a header row and the columns `campaign`, `month`
(`YYYY-MM`), `amount` and, optionally, `currency` (the upload box shows
the exact template). A file can be up to 1 MB, and its first 5,000 rows
are imported.

Each campaign has one cost per month, so saving or importing the same
campaign and month again replaces the amount. The campaign name is
matched to `utm_campaign` without regard to case. Without a currency a
cost uses the site currency. Other currencies are converted to it for
the report. A month's cost is spread evenly over its days, so a report
for part of a month counts part of the cost.

## UTM builder

**Campaigns → UTM builder** builds a tagged link from a landing page URL
and the five UTM values, and shows the link as you type. The presets
(Newsletter, Social post, Paid search, Paid social, Print / QR and
Partner) fill in the usual source and medium.

**Check link** checks every value. Capital letters are lowercased and
spaces become underscores. A value that looks like **personal data** (an
email address, an id or a long number) is an error, and no link is built
until you remove it.

**Copy** the link, or use **Save to library** to keep it in the
[link library](/docs/features/campaigns#link-library).

## Link library

**Campaigns → Links** keeps the tagged links your team uses, so everyone
copies the same URL instead of typing UTM values again. Save one from the
UTM builder with **Save to library**, or start from **New link**.

| Field | Rules |
|---|---|
| **Name** | Required, up to 120 characters. A label for the library, not part of the URL |
| **Landing page URL** | Required. Starts with `https://` or `http://`, has no spaces and is up to 2,048 characters |
| **Source, Medium, Campaign, Content, Term** | Optional `utm_*` values. Saved in lowercase, with spaces turned into underscores, and cut at 255 characters |
| **Tags** | Optional, separated by commas. Saved in lowercase. A tag is cut at 40 characters and a link keeps its first 20 tags |
| **Notes** | Optional free text, for example where the link is used |

A link is not saved when its UTM values look like personal data (an
email address, an id or a long number).

### The tagged URL

Every saved link shows its **tagged URL**: the landing page URL with the
link's UTM parameters added. If the landing page URL already has one of
those parameters, the link's value replaces it. Other query parameters
are kept. **Copy** puts the tagged URL on your clipboard, from the list
or from the link's own page.

### Search and tags

The list shows the newest links first. Search matches the name, the
landing page URL and the campaign. Choose a tag from the menu, or click
a tag on a link, to see only the links with that tag.

### QR codes

**QR code** on a link shows a code for its tagged URL, for posters,
flyers and packaging. **Download SVG** saves it as a vector file, which
scales to any print size.

> **Tip:** Scan the code with a phone before you send it to print.

### Links and reports

A saved link is the landing page URL itself, not a redirect or a short
link, so the library does not count clicks. Visits that arrive through
the link appear in the
[campaign report](/docs/features/campaigns#campaign-report) under its
campaign, source and medium, like any other tagged visit. A link with a
campaign has a **See campaign performance** shortcut to that report.

Deleting a link only removes it from the library. Copies already in
emails, ads or print keep working, and their visits stay in your
reports.

Anyone who can view the site can open the library, copy links and
download QR codes. Saving, editing and deleting a link needs the
`content.write` permission (see
[roles](/docs/teams/roles#permission-matrix)).

## UTM hygiene

**Campaigns → UTM hygiene** checks the `utm_source`, `utm_medium` and
`utm_campaign` values in the selected period and lists:

- **Near-duplicate values** that differ only by case, spaces or
  punctuation (`Facebook` vs `facebook`, `e-mail` vs `email`), with the
  visits for each and a suggested spelling.
- **Values to tidy** that break the lowercase, underscore style (capital
  letters, spaces, hyphens or other punctuation), with a suggested value.
- **Sources we don't recognize**: `utm_source` values that are not on the
  list of well-known sources.

These are suggestions only, and nothing is changed for you. Fix the
links at the source (the UTM builder keeps new ones consistent). **Set
up alias** opens **Site settings → Channels**, where a
[custom channel rule](/docs/metrics/channels#custom-channel-rules) can
put the variants in the same channel.

## Tips

- Use `utm_source` for where (newsletter, linkedin), `utm_medium` for the
  type (email, cpc, social) and `utm_campaign` for the campaign.
- `utm_medium` values like `cpc`, `paid` or `display` put visits in a paid
  [channel](/docs/metrics/channels), and `email` puts them in Email.
- Never put personal data (emails, customer ids) in UTM parameters.

## API

The campaign report, costs, builder, hygiene check and link library are
REST resources under `/sites/<site id>/campaigns` and MCP tools:

| Area | REST path | MCP tools |
|---|---|---|
| Campaign report | `/sites/<site id>/campaigns` | `campaigns_list` |
| Costs | `/sites/<site id>/campaigns/costs` | `campaign_costs_list`, `campaign_costs_create`, `campaign_costs_update`, `campaign_costs_delete`, `campaign_costs_import` |
| UTM builder | `/sites/<site id>/campaigns/builder` | `campaigns_builder` |
| UTM hygiene | `/sites/<site id>/campaigns/hygiene` | `campaigns_hygiene` |
| Link library | `/sites/<site id>/campaigns/links` | `links_list`, `links_get`, `links_create`, `links_update`, `links_delete`, `links_qr` |

`links_qr` returns the QR code as SVG text. Its optional `size` is the
module size in pixels, from 2 to 20. The [API reference](/docs/api)
lists every input.
