QRAnalytica

How Do I Track QR Code Scans in Google Analytics 4?

Add utm_source, utm_medium and utm_campaign to the URL inside your QR code, then find the scans in GA4's Traffic acquisition report. Steps, checks, fixes.

Nookesh Karri · 9 min read
Dark cover card with the title 'How Do I Track QR Code Scans in Google Analytics 4?' in white and a lime accent bar

To track QR code scans in Google Analytics 4, put UTM parameters on the URL inside the code, at minimum utm_source, utm_medium and utm_campaign, and send the code to a page that has your GA4 tag installed. Each scan then shows up in Reports > Acquisition > Traffic acquisition under the source, medium and campaign you chose. Without those tags, scans land in Direct, mixed in with everyone who typed your address.

What you need before you start

  • GA4 on the landing page. GA4 only records the visit if the page the code opens has your property’s tracking code. A landing page built in another tool and loaded in an iframe can miss it, and a code that points at someone else’s domain, such as a YouTube video, sends no campaign data to your reports at all (MeasureU).
  • A web page as the destination. Codes that open an email, a vCard, plain text, an SMS or a file download can’t be tracked in GA4. The workaround is to send the scan to a page on your site and put the download link there.
  • Names decided before printing. Pick your source, medium and campaign values now. You can’t edit a static code after it’s on paper.

Step 1: Choose your UTM values

Google’s help page on collecting campaign data with custom URLs lists the parameters and says you “should always use utm_source, utm_medium, and utm_campaign.” For a QR code, here is how I fill them in:

ParameterWhat it means for a QR codeExample
utm_sourceThe physical item carrying the codeyard_sign, table_tent, flyer
utm_mediumThe channel, the same on every printed codeqr
utm_campaignThe promotion or listingoak_street_open_house
utm_contentOptional: which version or placementfront_window, version_b

Two rules from Google matter here. Values are case sensitive, so utm_source=Flyer and utm_source=flyer become two rows in your reports. Google recommends lowercase and a strict naming convention. And any parameter you leave out shows up as “(not set)”.

Use utm_medium=qr on every code and put the detail in utm_source. Some guides suggest a medium of QR in capitals (KRM Digital). That works until one code goes out in lowercase, because you have to remember the capitals on every code for years.

Step 2: Build the tagged URL

Use Google’s Campaign URL Builder. Paste the landing page address, fill in the source, medium and campaign, and copy the URL it generates. For a real estate agent putting a code on a yard sign, the result looks like this:

https://example.com/listings/oak-street?utm_source=yard_sign&utm_medium=qr&utm_campaign=oak_street_open_house

Never put personal data in these values, such as a name or email address from a mailing list you used to generate personalized codes. Whatever is in the URL can appear in your GA4 reports, and MeasureU warns that this breaks Google’s rules and “can even lead to suspending your GA account.” If you need per-person tracking, a cookie-free scan count is the safer route; see our GDPR compliant QR code analytics guide.

Step 3: Make the code

The tagged URL is long, and a static code that stores the whole URL gets denser as the URL grows. Dense codes are harder to scan from a distance or in bad light, which is one of the causes in our QR code not scanning guide.

A dynamic code avoids that. The code stores a short link, and the redirect service sends the scan to your tagged URL. You can also change the destination later without reprinting, which helps when you notice a typo in utm_campaign after the flyers are back from the printer. Our dynamic vs static QR code guide covers the trade-off in more detail.

In QRAnalytica, you can add the UTM parameters to the redirect itself: UTM injection appends them to campaign redirects for Google Analytics. The Google Analytics integration page shows how that works.

Step 4: Check that it works

Don’t wait for the weekly report to find out the tagging is broken.

  1. Scan the printed proof with your phone, not a link copied to your laptop.
  2. Look at the address bar on your phone. The utm_ parameters should still be in the final URL. If they’re gone, something on the way stripped them (see the next section).
  3. Open Reports > Realtime in GA4. Google’s Realtime report “Displays user activity during the last 30 minutes,” and its source and campaign card should show your values within a few minutes.
  4. In the event card, click page_view and confirm the UTM values match what you typed in the builder.
  5. Check standard reports later. Google’s data freshness page lists a typical processing time of 2-6 hours for intraday data and 12 hours for daily data on standard properties.

Then go to Reports > Acquisition > Traffic acquisition, switch the primary dimension to Session medium, and look for the qr row. Add Session source as a secondary dimension to split it by yard sign, flyer or table tent. One detail confuses people: the Landing page + query string dimension leaves UTM parameters out, so don’t look for them there. They appear in Page location instead.

What goes wrong

Scans land in Direct

A scan from a camera app usually reaches your site with no referrer, so as KRM Digital puts it, the visit is “indistinguishable from someone typing the URL directly.” GA4’s default channel group files a visit under Direct when the source is “(direct)” and the medium is “(not set)” or “(none)”. If your code has no UTM tags, that’s where its scans go.

If you did tag the URL and scans still show as Direct, look at redirects. ObservePoint calls redirects “the most common ‘silent killer’ of marketing attribution,” because a redirect that drops the query string turns a tagged visit into a Direct one (ObservePoint). The usual suspects are a move from http to https, from the bare domain to www, or an old page redirecting to a new one. Test the final URL in the code and check the parameters survive to the address bar.

Scans land in Unassigned

GA4 uses Unassigned “when there are no other channel rules that match the event data.” The default rules recognize mediums like referral, email and banner, but qr isn’t one of them, so tagged QR traffic can end up there. The data is still correct when you filter by Session medium. If you want a “QR” row in channel reports, create a custom channel group in Admin > Data display > Channel groups with a channel whose medium exactly matches qr. Put it above the other channels, because traffic goes into the first channel whose conditions it matches. Google says custom channel groups can be applied to your reports retroactively, so you don’t lose earlier scans.

Two rows for the same campaign

Case sensitivity again: Spring_Menu and spring_menu are different values.

Fewer scans in GA4 than you expected

GA4 will never record every scan. Script blockers and visitors who refuse cookies can stop the tag from firing, and reports can show “(not set)” or thresholded data. That’s the real limitation of this method: GA4 measures visits to your page, not scans of the code. If you need a count of every scan, you need a count taken at the redirect. QRAnalytica’s dynamic codes run through its own redirect servers, which is what makes its scan counts possible, and it collects that data without cookies. The trade-off is a dependency: the code relies on that redirect service staying in place.

Where to go next

Once the tagging works, use one utm_source per placement so you can compare them. The same approach works for billboards and posters, covered in our OOH QR code tracking guide.

FAQ

Why do my QR code scans show up as Direct in GA4?

A scan from a phone camera usually arrives with no referrer, so GA4 can’t tell it apart from someone typing your address. Unless the URL in the code carries UTM parameters, the visit is filed under Direct. If you did tag it, check that no redirect on the way drops the query string.

Which UTM parameters do I need for a QR code?

Google says to always use utm_source, utm_medium and utm_campaign. For QR codes, set the source to the printed item, the medium to qr, and the campaign to the promotion. Add utm_content if you want to tell two versions of the same piece apart.

How long until QR scans appear in GA4 reports?

The Realtime report usually shows a test scan within a few minutes. Standard reports take longer: Google lists 2-6 hours for intraday data and 12 hours for daily data on standard properties.

Can I track a QR code that opens a vCard, a PDF or a text message in GA4?

Not directly. GA4 only records a scan when the code opens a web page that has your GA4 tag on it. Point the code at a page you control first, and put the download or contact details there.

Sources

Track your dynamic campaigns. 7-day trial, no credit card.
Generate Dynamic QR