Why GA4 doesn’t count QR code scans
Updated by the UTM Builder team at Limner.
Because the scan doesn’t happen on your site. The camera reads the code, shows the link, and only then does the browser open the page. GA4 only exists from that moment on, and only if the page loads with the tag.
The path from scan to visit
- The camera decodes the QR code. In a static QR code, the link is encoded in the pattern itself, so nothing goes over the internet at that point.
- The person taps the link, or gives up.
- The browser opens the URL. If a redirect strips the query string, the parameters are lost.
- The page loads and the tag fires. Google’s help says the
session_startevent carries the information that determines attribution, such as UTM parameters and the referrer.
Only step 4 shows up in GA4. That’s why there’s no scan metric in the report. There are sessions.
What about scan counters?
Scan counts come from dynamic QR codes. A dynamic code points to an address owned by the vendor, which logs the hit and redirects to your site. The count belongs to the vendor, not to GA4, and the code only works as long as that service stays online. A static QR code has no middleman: it never expires, but nobody counts the scans either.
Why GA4 shows fewer
- The person scanned the code and didn’t open the link.
- The page didn’t finish loading, because of a weak signal or a slow load.
- A blocker or declined consent. Google’s help lists blockers among the causes of visits with no source, and what GA4 records without consent depends on how consent mode is configured.
- A redirect stripped the UTMs and the visit came in as (direct) / (none) instead of landing in the campaign.
- The same person scanned twice within a few minutes. A new campaign in the middle of a session doesn’t start a new session.
How to measure QR codes with what you have
- Add UTMs to the QR link:
utm_sourcewith the piece or the location,utm_medium=offlineand the campaign. One QR code per piece, each with a differentutm_content, lets you compare them. - Test before you print: scan it, open it and check the Realtime report to see if the campaign shows up.
- Open the final URL and check that the parameters are still there after the redirects.
- Create an Offline channel in a custom channel group. Without it, the
offlinemedium falls into Unassigned. - Read the results as sessions and key events per piece, not as scans.