Every QR code scan without UTM parameters looks identical in GA4 to someone who typed your URL directly into their browser. There is no referrer, no channel, no campaign — just another session in the Direct bucket.
The fix is straightforward once you understand why it happens and what order to do things in. QR codes do not pass a referrer header when they open the destination URL. UTM parameters are the only mechanism that carries campaign attribution from the physical print material into your analytics platform.
This guide covers the exact UTM values to use for QR campaigns, why you should shorten the URL before generating the QR code, how to manage multi-placement campaigns with utm_content, and where to find the data in GA4 after launch.
Why QR code scans appear as Direct traffic in GA4
When you click a hyperlink on a web page, the browser sends a Referer header to the destination server, identifying the page you came from. GA4 uses that header to attribute the session to the correct source — the website that sent the traffic.
When a phone camera scans a QR code and opens the URL, no Referer header is sent. The phone reads the URL from the QR pattern and opens it directly in the browser. From the browser's perspective, it is a fresh navigation — exactly like typing the URL manually. GA4 sees no referrer and classifies the session as Direct.
UTM parameters bypass this limitation by embedding campaign attribution directly in the URL. When the destination page loads, GA4 reads utm_source, utm_medium, and utm_campaign from the query string and attributes the session accordingly. The Referer header is irrelevant — the UTMs carry the full attribution.
This is why every QR code used in a marketing campaign must encode a UTM-tagged URL. Without UTMs, QR traffic is permanently hidden inside the Direct bucket, merged with bookmark clicks, manually typed URLs, and other unattributable traffic.
The recommended UTM structure for QR codes
Three UTM parameters are essential for QR campaigns. Two more are optional but add useful granularity.
utm_source identifies where the traffic came from. For QR codes, use utm_source=qr_code as a consistent value across all campaigns. This makes it trivial to filter all QR traffic in GA4 with a single rule, regardless of which campaign, which placement, or which medium the code appeared in.
utm_medium identifies the channel category. For physical printed materials — posters, flyers, packaging, business cards, menus, direct mail — use utm_medium=print. For non-print physical contexts like event screen displays, digital signage, or TV overlays, use utm_medium=offline. Avoid utm_medium=qr — it does not match any of GA4's default channel grouping definitions, so sessions will land in the Unassigned channel bucket rather than a meaningful category.
utm_campaign identifies the specific initiative. Include a date suffix in YYMMDD format so campaigns with the same name in different years remain distinct in reports. Use utm_campaign=store_opening_260520 rather than utm_campaign=store_opening. All lowercase, underscores instead of spaces.
utm_content is optional but valuable when running multiple QR codes for the same campaign. It distinguishes placements — utm_content=window_decal vs utm_content=receipt_back vs utm_content=counter_card. This lets you compare performance of each placement within the same campaign report.
utm_term is designed for paid keyword tracking and is rarely useful for QR campaigns. Skip it unless you have a specific reason to use it.
Why URL length matters and why you must shorten first
A QR code encodes data as a matrix of black and white modules. The more data encoded, the more modules are needed, and the denser and smaller those modules become. Dense QR patterns are harder for cameras to decode — they require better lighting, a steadier hand, and a higher-resolution camera.
A destination URL with five UTM parameters can easily reach 150 to 200 characters. Encoding 200 characters into a QR code produces a Version 11 or higher QR at minimum, with modules small enough to cause scan failures on older smartphones, at small print sizes, or in poor lighting.
The solution is to shorten the UTM-tagged URL to a short link before generating the QR code. The short link typically encodes 20 to 30 characters — a Version 2 or 3 QR code with large, easy-to-scan modules. The UTM parameters are stored in the redirect platform's database, not in the QR pattern itself. Every scan hits the redirect server, gets the UTM-tagged destination URL, and follows the redirect — the QR remains simple, and the UTMs still arrive at the destination page.
The shortening step also gives you two layers of analytics: click data logged at the redirect server (device, location, volume), plus campaign attribution in GA4 via the UTMs. Both layers report on the same physical QR code placement.
Static vs dynamic QR codes for UTM campaigns
A static QR code encodes the destination URL permanently into the pattern. If the URL changes after printing — because the landing page was moved, the UTMs need updating, or you want to A/B test destinations — you must reprint the physical material with a new QR code.
A dynamic QR code encodes a short redirect URL. The actual destination (with UTMs) is stored in the link platform's database and can be updated at any time without touching the physical print material. The QR pattern stays unchanged.
For any UTM campaign that involves printed materials — especially campaign materials printed in volume like brochures, packaging inserts, or event signage — use dynamic QR codes. The ability to update the destination after print is the critical capability. If you discover your UTMs are incorrectly formatted, or you want to change the landing page mid-campaign, you update the destination link in your platform. Every future scan from the already-printed code goes to the new destination with the corrected UTMs.
Dynamic QR codes also provide scan analytics at the platform level — volume, device, geo, time — which complements the UTM attribution data in GA4. Static QR codes with UTMs provide GA4 attribution but no platform-level scan analytics.
Step-by-step: building a UTM-tagged QR code
Step 1: Build the UTM-tagged destination URL. Start with the landing page URL. Append your UTM parameters. Use all lowercase and underscores. For a table card in a restaurant summer campaign: https://yoursite.com/menu?utm_source=qr_code&utm_medium=print&utm_campaign=summer_menu_260520&utm_content=table_card
Step 2: Shorten the UTM-tagged URL. Paste the full UTM URL into LinkLab or your chosen link shortener. The platform creates a short redirect URL (for example, lnk.in/abc123) and stores your UTM-tagged destination URL. This is the URL you will encode into the QR code.
Step 3: Generate the QR code from the short link. Use your link platform's built-in QR generator pointing at the short link URL. Download in SVG for print or PNG at minimum 1000px for digital use.
Step 4: Test before committing to print. Scan the QR code with your phone and confirm it opens the correct page. Then open GA4, navigate to Reports > Acquisition > Traffic Acquisition, and verify the test session appears with the correct utm_source, utm_medium, and utm_campaign values. Only approve print after this test confirms the UTM data appears correctly in GA4.
Step 5: Monitor after launch. Give the campaign 24 to 48 hours after print materials go out before drawing conclusions. Review the Traffic Acquisition report weekly during the campaign period.
Managing multi-placement campaigns with utm_content
Many QR campaigns span multiple physical placements — the same offer promoted on a window decal, a receipt, a table card, and a takeaway bag. All four placements lead to the same destination page, but you need to know which one drove the most scans and the highest conversion rate.
The utm_content parameter handles this. Create four separate UTM-tagged URLs with identical utm_source, utm_medium, and utm_campaign values, but distinct utm_content values: utm_content=window_decal, utm_content=receipt_back, utm_content=table_card, utm_content=takeaway_bag.
Shorten each UTM URL separately in your link platform and generate a separate QR code from each short link. Print each QR code on the appropriate material.
In GA4, navigate to Traffic Acquisition and break down the qr_code / print rows by Session manual ad content (the GA4 dimension that corresponds to utm_content). You will see individual rows for each placement, comparable on session count, engagement rate, and conversions. This tells you whether the window decal or the table card drove better post-scan behaviour — enabling data-driven decisions about where to invest next campaign.
Finding QR traffic in GA4 reports
In GA4, go to Reports > Acquisition > Traffic Acquisition. This report groups sessions by source and medium. If your UTMs are set up correctly, you will see a row for qr_code / print (source / medium) within the Session default channel group.
If you see Direct / (none) instead of qr_code / print, there are three common causes: the UTM parameters were missing from the destination URL when the QR was generated; the landing page URL stripped the UTM parameters before the analytics script fired (some redirect configurations do this); or the analytics script on the destination page was blocked by an ad blocker.
To verify UTMs are intact on arrival, add a test scan and check GA4's real-time report (Reports > Realtime) during the scan. If the session appears under Direct rather than your expected campaign source, inspect the URL in the browser after the QR scan to confirm the UTM parameters are present in the address bar.
For campaign-level detail, use the Campaigns report or create a custom exploration. Segment by utm_campaign to compare different QR campaigns. Add utm_content as a secondary dimension to compare placements within a campaign. Export to Looker Studio for shareable dashboards if reporting to stakeholders.