UTM parameters and QR codes: track which printed material drives sales
You put the same offer on a window decal, 5,000 flyers, a table tent, and an insert in every shipped box. Sales went up. Which one did it? Scan counts on their own cannot answer that, and UTM tags on their own cannot either. Wire them together, one dynamic link per printed piece with its own tagged destination, and every order traces back to the physical thing somebody was holding.
The question has two halves, and they live in different systems
A scan is the only thing that happens on the printed side, and the only place it can be counted is the redirect in the middle. That is half one, and it is what a dynamic QR link gives you: this decal was scanned 312 times, mostly on iPhones, mostly between 11am and 1pm.
Everything after the scan happens on your website: the session, the add to cart, the order. Your own analytics or ecommerce platform owns that half, and it can only see what the incoming URL tells it. UTM parameters are that message, five optional pieces of text you append to a link so the visit arrives already labelled.
Neither half answers the question alone. A code with 400 scans and no revenue looks identical to a code with 400 scans and 40 orders until the destination carries an identity your analytics can group by. And revenue attributed to "print" tells you nothing about which print. The fix is to make the pairing one to one: one dynamic link per physical piece, one UTM tag set per dynamic link.
Put the tags on the destination, never on the printed code
This is the part most people get backwards, so it is worth being precise. With a dynamic link there are two URLs: the short one that gets encoded into the printed image, and the destination you can edit afterwards. The UTM parameters belong on the destination.
- A typo becomes an edit instead of a reprint. Misspell
utm_campaginon a static code and 5,000 flyers are now untrackable. On the destination, you fix it in ten seconds and every future scan lands correctly tagged. - The code stays sparse. A static code encodes every character you give it, so a URL carrying four parameters produces a visibly denser grid that needs more size, better contrast, and flatter stock to scan reliably. A short link is a short link no matter how long the tagged destination gets.
- You keep the scan number. Tagged or not, a static code cannot report anything, because nothing sits in the middle to count. The redirect is what makes scans visible at all.
One mechanical detail worth knowing before you plan around it: appending parameters to
the short URL does not work. A Reticle dynamic link sends the scanner to the
destination exactly as stored, so open-qr.link/aB3xY9?utm_source=flyer and
the bare short link behave identically. Store the tags in the destination, which you can
change whenever you like under My codes.
A tagging scheme that still makes sense in a year
There is no official standard for print, so the goal is a convention you will not abandon halfway through. This one holds up:
utm_sourceis the placement:window-decal,table-tent,box-insert,yard-sign. The physical thing.utm_mediumisqr, on every single one. This is what lets you separate all scanned traffic from email, social, and paid in one grouping.utm_campaignis the promotion or season:spring-2026,grand-opening.utm_contentis the workhorse for print: the specific run, location, or variant.store-42,run-b,counter-vs-door. When two pieces are otherwise identical, this is the field that tells them apart.utm_termis for paid search keywords. Leave it out of print.
Three rules that matter more than the scheme itself. Keep every value lowercase, because
most analytics tools treat Flyer and flyer as two separate
sources. Use hyphens rather than spaces or underscores. And freeze the vocabulary before
the first print job, since renaming flyer to flyers in week
three splits one campaign into two rows that no report will ever recombine.
A four-piece campaign ends up looking like this:
- Window decal:
yoursite.com/offer?utm_source=window-decal&utm_medium=qr&utm_campaign=spring-2026 - Table tent:
yoursite.com/offer?utm_source=table-tent&utm_medium=qr&utm_campaign=spring-2026 - Flyer, downtown drop:
yoursite.com/offer?utm_source=flyer&utm_medium=qr&utm_campaign=spring-2026&utm_content=downtown - Box insert:
yoursite.com/offer?utm_source=box-insert&utm_medium=qr&utm_campaign=spring-2026
Four destinations, four dynamic links, four QR codes that look different in the printer and identical to the person scanning them.
Building it
For a handful of pieces, do them one at a time. Open the
QR generator, switch the URL tab to Dynamic,
and paste the full tagged destination including the query string. Give the link a name
that matches the physical piece ("Window decal, spring") rather than the URL, because
that name is what you will be reading in the scan report six weeks later. Add a label
like spring-2026 so the whole campaign filters as a group under
My codes. Then style and download the code, or take the
Print pack if it is going to a printer, which gives you a 300 DPI PDF
with crop marks and bleed, an EPS, the SVG, and a PNG proof in one ZIP.
For twenty pieces, do not do that twenty times. Reticle Pro imports a CSV with the
headers destination,name,labels and mints up to 100 dynamic links in one
pass, which is exactly the shape a tagging spreadsheet already has: one row per printed
piece, the tagged URL in one column, the human name in the next. There is a sample CSV
to download in the import dialog.
A useful accident of that importer: it refuses two rows with the same destination. If a row is rejected as a duplicate, you have found two printed pieces you would never have been able to tell apart in a report, which is a tagging bug caught before the print run rather than after it.
Tagging by device, without a second code
A single printed code can send iPhone and Android scanners to different destinations
through routing rules, and because each rule
carries its own URL, each one can carry its own tags. Point the iOS rule at
?utm_content=ios and the Android rule at ?utm_content=android
and one poster reports two audiences separately, all the way through to the order.
The same applies to rules on country, browser language, or the local time at your business. And you are not taking it on faith: the scan activity list marks which rule handled each scan, so you can confirm the routing fired before you trust the split in your analytics.
Reading the two reports side by side
Under My codes, each link shows its lifetime scan count, a chart you can flip between 14, 30, and 90 days, and breakdowns by device, hour of day, and country. That is the printed side, and it is on every plan. On Pro, each scan is also kept as its own row for about 90 days with a time, an approximate city and country, the device, and which destination it was sent to, exportable to CSV. You can also select links and export the list itself, with names, destinations, labels, and scan counts, which is the join table between your printed inventory and your analytics report.
On the other side, group your sessions and conversions by source, medium, campaign, and content. Now the two reports line up row for row, and the interesting number is the one neither report shows on its own: the gap between scans and sessions. Four hundred scans producing sixty sessions is not a measurement error, it is sixty seconds of loading, a redirect chain, or a landing page that did not deserve the scan. That gap is only visible because you counted both ends.
Five mistakes that quietly ruin the data
- Tagging the short link. Covered above, and the failure is silent: the scan works, the visit arrives untagged, and nothing anywhere reports an error.
- One link across several pieces. The most common one. Reusing a single code on the decal and the flyer because "it goes to the same page" throws away the entire question you are trying to answer.
- Changing the vocabulary mid-campaign. Every rename splits a row. Decide the values once, write them in the same spreadsheet you import from, and treat that file as the record.
- Tagging your own internal links. UTM parameters are for traffic arriving from outside. Putting them on a link between two of your own pages restarts the session attribution and overwrites the original source, which is how a print campaign ends up credited to your own homepage.
- Letting a tagged URL escape. Someone scans the decal, likes the page, and shares the tagged URL to a group chat. Every one of those visits now reports as the decal. A correct canonical tag on the landing page keeps the tagged variants out of search results, and it is worth knowing this is the one leak the tagging scheme cannot fix on its own.
Frequently asked questions
Can I add UTM parameters to a QR code?
Yes, and the right place for them is the destination URL, not the printed code. With a dynamic link, the code encodes a short URL and the tagged destination sits behind it, so you can fix a typo in a UTM value or rename a campaign without reprinting anything.
Do UTM parameters make a QR code harder to scan?
On a static code, yes. Every character of the tagged URL is encoded in the image, so a long query string makes a denser code that needs to be printed larger or scanned closer. On a dynamic link the printed data is just the short URL, so the tags cost nothing at all in scannability no matter how long they get.
What UTM values should I use for printed materials?
A workable scheme is utm_source for the placement (window-decal, table-tent, box-insert), utm_medium=qr so every scan is separable from your other channels, utm_campaign for the promotion, and utm_content for the specific print run or location. Consistency matters more than the exact scheme: pick lowercase, hyphenated values and never change them mid-campaign.
Will Reticle pass query parameters I add to the short link?
No. A dynamic link sends the scanner to the destination exactly as you stored it, so anything you append to the short URL is not carried through. Put the UTM parameters in the destination itself, which you can edit at any time under My codes.
Do I need a paid plan to track materials separately?
Not to start. The free plan includes 3 dynamic links, each with its own scan count and aggregate breakdowns, which is enough to compare three printed pieces. Reticle Pro adds unlimited dynamic links, individual per-scan records, CSV import for minting many links at once, and routing rules.
Start with the piece you are least sure about. Open the QR generator, switch the URL tab to Dynamic, and paste your destination with its tags already on it. Free, 3 dynamic links included, and Pro when one code per printed piece starts to mean more than three.