Tracking
Tracking printed QR codes with UTM parameters
How to tag a printed QR code so scans show up as something other than direct traffic, what the tags cost in module count, and a naming scheme that survives.
Four thousand people scanned the campaign, the site had a good month, and the analytics say “direct / none”. There is no way to tell the poster in the station from the table tent in the cafe, because a camera app opening a link sends no referrer at all. The browser has no previous page to report, so every scan lands in the same bucket as a typed URL.
Query-string tags are the only signal that crosses from paper into the browser.
The five parameters
| Parameter | Carries | Offline example |
|---|---|---|
utm_source | Where the visit came from | poster-station-north |
utm_medium | The kind of channel | qr |
utm_campaign | Which campaign or print run | autumn-menu-2026 |
utm_content | Which variant of the creative | a4-poster |
utm_term | Keyword; paid search only | Usually empty offline |
They are ordinary query-string parameters, so ?utm_source=…&utm_medium=… on
the end of your URL. Analytics tools read them and attribute the session. GA4
also accepts a sixth, utm_id, for pairing a visit with a cost record; for
print you can normally ignore it.
Conventions that hold up offline
The digital conventions map badly onto physical objects, so most teams settle on the same three rules.
utm_medium is the constant. Use qr or offline and never vary it. Its
job is to let you pull every scan across every campaign into one row. Pick one
of the two and write it into whatever document your agency reads, because a
report split between qr, QR and offline is three reports.
utm_source names the physical placement. Not “print”, not “poster” — the
specific thing in the specific place. poster-station-north and
poster-station-south are different sources because they answer different
questions. This is the field that earns its keep.
utm_campaign is the print run. One campaign value per batch of artwork
sent to the printer. When you reprint in March with a new offer, that is a new
campaign, even if the poster looks identical.
Lower case throughout, hyphens rather than spaces or underscores, and no
punctuation that needs URL-encoding. Analytics tools treat Poster and poster
as two different values, and a space becomes %20 inside the code, which costs
modules and looks broken when anyone reads the URL aloud.
A naming scheme
| Placement | utm_source | utm_medium | utm_content |
|---|---|---|---|
| A4 poster, north entrance | poster-station-north | qr | a4-poster |
| A4 poster, south entrance | poster-station-south | qr | a4-poster |
| Table tent, cafe | menu-table-tent | qr | tent-v2 |
| Sticker on the window | window-sticker | qr | vinyl-120mm |
| Printed on the box | packaging-box | qr | sleeve-back |
| Leaflet in the parcel | parcel-insert | qr | a6-flyer |
| Business card | business-card | qr | card-2026 |
| Exhibition stand | stand-hall7-b12 | qr | banner-3m |
utm_campaign stays the same across every row for one print run —
autumn-menu-2026 — which is what makes the rows comparable.
Tag before you print
This is the part that gets people. The tagged URL is what the symbol encodes. There is no server in the middle to change your mind at, and no code generated here expires or redirects — the link you typed is the link the code contains, permanently.
So build the URL first, tag it, then generate. The generator has a UTM section in the QR panel that appends only the fields you fill in and encodes the assembled URL, which at least removes the risk of a typo between the spreadsheet and the artwork. Whether a code can be re-pointed after printing is the whole subject of static versus dynamic codes; with a static code the answer is no.
What the tags cost in modules
Tags are not free. Take a menu link:
https://oakleaf.example/menu
Twenty-eight characters, version 3 at error correction M — 29 modules across. Now tag it properly:
https://oakleaf.example/menu?utm_source=table-tent&utm_medium=qr&utm_campaign=autumn-menu-2026&utm_content=table-tent
That is 117 characters and a version 7 symbol: 45 modules. Four versions up, and
about 55% more modules per side. Add utm_term and a longer source name and you
are at 144 characters, version 8, 49 modules.
Module count is what sets minimum print size, so:
| Payload | Modules | Floor at 0.4 mm | Module size if printed at 2 cm |
|---|---|---|---|
| Plain URL | 29 | 1.2 cm | 0.69 mm |
| Four UTM tags | 45 | 1.8 cm | 0.44 mm |
| Five UTM tags | 49 | 2.0 cm | 0.41 mm |
At a fixed 2 cm — a table tent, a business card, the back of a pack — a fully tagged URL puts each module within a whisker of the 0.4 mm print floor described in the print size guide. It will still scan on a good phone in good light. It will fail on a cheap one in a dim room, which is exactly the situation printed codes live in.
On a poster read from two metres you need 20 cm of code anyway, so the extra density is irrelevant. On anything small, it is the whole problem.
The short redirect
If the tagged URL is too dense for the space it has, encode a short path on a domain you own and attach the tags on the far side of the redirect: the symbol stays small, the analytics tool still receives the parameters, and the visitor still lands on the destination. That whole trade — the module counts, the 302-not-301 detail, and the conditions under which renting a redirect is the wrong call — is the subject of static versus dynamic QR codes.
The part that belongs here is the tagging discipline it demands. Keep a record
mapping each short path to its placement, because oakl.ea/m2 tells nobody
anything six months later, and give each placement its own path so the
per-placement breakdown survives. If you cannot commit to running the redirect
for as long as the print exists, print the long tagged URL and print the code
bigger. A dead redirect is worse than a dense code.
Reading the result
In GA4, Reports → Acquisition → Traffic acquisition, then change the dimension
to Session source / medium or Session campaign. Your rows appear as
poster-station-north / qr.
One warning: GA4’s default channel grouping does not know what qr is, so those
sessions land in Unassigned rather than a named channel. offline behaves
the same way. Either accept that and work from the source/medium report, or
create a custom channel group in Admin that maps utm_medium = qr to a channel
of your own. Set it up before the campaign starts, so nobody spends the first
week reporting that the posters produced nothing.
Cookieless tools handle this more simply. Umami, Plausible and Fathom all read
the utm_ parameters off the pageview and list them in a campaigns breakdown
with no cookie and no consent banner, because the attribution is attached to the
pageview rather than to a person followed over time. For counting scans per
placement — which is the actual question — that is enough, and it is why this
site’s own pages use a cookieless tool.
Whatever you use, check one thing on the day the print arrives: scan the real object with a real phone and confirm the tagged hit appears in the live view. The most expensive attribution bug is the one discovered after five thousand menus have been laminated. The restaurant menu guide covers the rest of that pre-launch check.
Frequently asked
Why do QR code scans show up as direct traffic?
What should utm_source be for a printed QR code?
Do UTM parameters make a QR code harder to scan?
Can I change the UTM tags on a code after it is printed?
- utm
- analytics
- attribution
- ga4
Make the code this guide describes
The generator runs in your browser — add a logo, pick colours, tag the link with UTM parameters and download a PNG or SVG. No account, no watermark.
Keep reading
-
Tracking
Static vs dynamic QR codes, and which one you actually need
Dynamic codes buy an editable destination and scan analytics, and charge rent for both. Here is what each type costs and the middle path most people want.
-
Printing
What size should a printed QR code be?
The distance-to-size rule that decides whether a printed QR code scans, the minimum millimetres per module, and the quiet zone people keep cropping off.
-
Use cases
QR code menus people actually manage to use
Placement, size and lighting for a QR menu in a real dining room, why serving a PDF is the usual mistake, and the tamper check every venue should be doing.