QR Code Analytics and Tracking: Measuring What Actually Matters

Scan counts lie. Real QR measurement is the funnel from scan to landing to conversion — UTM conventions, attribution gotchas, and what each analytics layer actually sees.

Rehan Haider
By Rehan Haider
May 9, 2026
QR Code Analytics and Tracking: Measuring What Actually Matters

Scan counts are the most popular QR metric and the most misleading. A QR provider tells you a code was scanned five hundred times last month, the report looks healthy, the team feels productive, and nobody notices that only twelve people made it to the form. The honest measurement question for a QR codeA 2D matrix barcode that encodes data in a square grid of black and white modulesA single black or white square in the QR grid. The number of modules per side scales with the QR versionThe size of a QR code, numbered 1 (21×21 modules) through 40 (177×177). Higher versions store more data but require more printed space. Read more →, from 21×21 modules for version 1 up to 177×177 for version 40. Read more →. Read more → is the same as for any other marketing surface: how does scan turn into landing, and how does landing turn into a conversion. This post covers the funnel, the analytics layers that see it, the attribution traps that distort the numbers, and what to do when you cannot use a dynamic redirect at all.

Why scan count alone is misleading

A scan event tells you exactly one thing: a camera decoded the symbol and the phone resolved the URL. It does not tell you whether the page loaded, whether the user stayed past the first second, whether the layout rendered, whether the offer matched intent, or whether anyone converted. Scan count is the top of a multi-step funnel, and treating it as the funnel collapses every interesting question into a single vanity number.

A more useful frame: scan is the same kind of metric as ad impression. It is a necessary first step that proves placement reaches an audience. It is not, by itself, evidence of business outcome.

The funnel I look for in production:

  1. Scan event — a camera resolved the symbol. Captured by the platform-level redirect or, in static-code workflows, inferred from landing-page hits.
  2. Landing-page session — the destination page loaded and the analytics tag fired. GA4, Plausible, or server logs can see this.
  3. Engagement signal — scroll depth, time on page, secondary navigation. Tells you the page held attention past the bounce window.
  4. Conversion event — the action you defined as success: sign-up, purchase, menu order, download, form submission. Defined in your analytics platform as a goal or event.
  5. Downstream value — revenue, lifetime value, retention. Lives in your CRM or product analytics, not the campaign dashboard.

A campaign that shows ten thousand scans and forty conversions has a 0.4 percent funnel. That is the diagnostic question, not “did people scan.”

The two analytics layers and what each one sees

QR measurement gets confused because two different systems are running, and each sees a different slice of the journey. Knowing which layer sees what saves a lot of “why don’t these numbers match” arguments.

Platform-level redirect analytics. This is what dynamic-QR vendors and short-URL services capture. When the user scans, the phone hits the vendor’s redirect endpoint before the destination loads. The vendor logs the request — timestamp, user agent, IP-derived approximate location, sometimes referrer. Then the redirect fires and the user lands on the destination. This layer sees every scan that completes the redirect, including scans where the user closes the tab before the destination renders. It does not see anything that happens on the destination page.

Landing-page analytics. This is GA4, Plausible, Fathom, or your own server logs. The tag or log fires when the destination page loads in the browser. This layer sees everything on the page — referrer, UTMs, scroll, clicks, conversions — but only for users who actually reached the page. Anyone who scanned but bounced before the page rendered is invisible here.

The two layers will never produce identical numbers, and that is fine. The platform layer is upstream and over-counts the audience that landing-page analytics will see. Reconciling the gap (usually 5-20 percent depending on connection quality and bounce behaviour) is one of the cleanest diagnostics for whether a campaign has a placement problem or a page problem.

What each analytics layer sees in the QR funnel A four-stage funnel diagram showing the scan-to-conversion journey: phone scan, vendor redirect server, destination landing page, and conversion event. Two horizontal bars indicate which analytics layer captures which stages — platform redirect analytics covers the scan and redirect steps, and landing-page analytics covers the page load and conversion steps. The overlap region in the middle is highlighted, with annotations explaining that the gap between the two layers is the bounce-before-paint cohort. What each analytics layer sees scan camera resolves URL redirect vendor server 302 brand.com/spring landing page conversion platform redirect analytics scan, user agent, approx. location, time landing-page analytics (GA4 / Plausible / logs) UTMs, referrer, scroll, clicks, conversion The gap between the two layers Platform sees more scans than landing-page analytics sees sessions. The delta is the bounce-before-paint cohort: users who scanned but closed the tab before the page rendered. A 5–20% gap is normal on mobile. A 50%+ gap means a slow page, a redirect loop, or a broken UTM. Diagnostic shortcut If platform scans = 10,000 and GA4 sessions = 9,200 → healthy 8% gap, page is doing its job. If platform scans = 10,000 and GA4 sessions = 3,400 → either the page is broken or UTMs are stripped on redirect.
The two analytics layers see overlapping but non-identical slices of the same journey. Reconciling the gap is one of the cleanest diagnostics in the toolkit — a healthy delta is single-digit; a large delta points at the page or the redirect, not the placement.

UTM conventions per surface

UTM parameters are still the lingua franca of campaign attribution because GA4 and most other analytics tools key off them automatically. The convention I use, after watching too many teams reinvent it badly:

  • utm_source — the surface or medium-specific origin. poster, packaging, flyer, business-card, tradeshow, tv-ad. Granular enough to distinguish channels of similar type.
  • utm_medium — always qr for scan-originated traffic. Keeping this stable means a single GA4 segment (“medium = qr”) instantly shows the entire QR portfolio across surfaces.
  • utm_campaign — the campaign or initiative, slugged consistently. spring-2026-launch, menu-refresh-q2. Not the same string as the page slug — it should outlive the URL.
  • utm_content — placement-level detail. citymall-poster, pkg-back-label, event-tabletent-3. This is where per-placement tagging lives.
  • utm_term — rarely useful for QR. Reserve for paid-search-style keyword data if your stack uses it.

A full URL example for a poster placement:

https://brand.com/spring?utm_source=poster&utm_medium=qr&utm_campaign=spring-2026-launch&utm_content=citymall

Two implementation rules that catch most bugs:

  1. Lowercase, hyphenated values everywhere. GA4 treats Poster and poster as different sources, which fragments reports.
  2. Test the full encoded URL by scanning the printed proof, not just the digital file. Some redirect chains strip query strings; some printers’ QR test tools regenerate the symbol with a different URL.

Refer to the official GA4 UTM documentation for the exact parameter names and how Google’s auto-tagging interacts with manual UTMs.

Per-placement tagging conventions

The single biggest determinant of whether you learn anything from a campaign is whether you tagged each placement uniquely. Two posters with identical UTMs are indistinguishable in the dashboard. Five franchise locations with the same code on the counter is a single line in the report. Per-placement tagging is the cheapest way to get signal granular enough to act on.

The patterns that work in production:

  • Per-placement utm_content. Keep utm_source, utm_medium, utm_campaign shared across placements within a campaign; vary utm_content per physical or logical placement (citymall, airport-t2, franchise-001).
  • Per-placement short-URL slugs. brand.link/spring-citymall, brand.link/spring-airport. Slug-level slicing is sometimes cleaner than UTM slicing because the redirect-vendor dashboard groups by slug natively.
  • Per-placement clean paths. brand.com/p/spring/citymall instead of UTMs. Useful when you control the destination domain and want server-log-friendly URLs without query strings. Keeps cleaner referrer behaviour through some redirects.

I default to utm_content for digital-adjacent surfaces and clean slugs for permanent print where I want the URL itself to be human-readable. The mechanism matters less than the consistency.

For a deeper read on the redirect mechanic and when each code type fits, see static vs dynamic QR codes; for the broader trade-offs between QR and short URLs, see QR vs short URL.

Attribution gotchas that distort the numbers

Several real-world quirks make scan attribution noisier than it should be. Knowing them up front saves the “why don’t iOS and Android numbers match” debate.

iOS Mail Privacy Protection. Apple’s MPP, introduced in iOS 15, pre-fetches images and links in Mail under specific conditions. For QR codes specifically, the impact is indirect — it affects email-side first-touch attribution more than scan logs — but if your campaign uses email as a follow-up to a scanned action, expect inflated open data and obscured first-click signal on iOS users.

Safari Intelligent Tracking Prevention. ITP shortens cookie lifetimes for cross-site tracking and limits third-party cookies. This affects multi-touch attribution windows on iOS more than first-party scan logging. If your dashboard expects a 30-day cookie window and Safari is silently giving you 7 days for cross-site cookies, your iOS conversion data looks lower than reality.

Walled-garden in-app browsers. Scans from within Instagram, Facebook, TikTok, and similar in-app browsers route through that platform’s own user agent and referrer rules. Some pass standard Referer headers, some do not, and some sandbox cookies into the in-app browser context. Scans from these contexts often look like direct/unknown traffic in landing-page analytics even when the QR was clearly the source — UTMs in the encoded URL are the reliable fallback.

Universal Links and app-redirect handoffs. iOS Universal Links and Android App Links can intercept a scanned URL and open the corresponding native app instead of a browser. The user reaches the right surface, but landing-page analytics never fires because the page never loads. Test on a clean device with the relevant apps both installed and uninstalled.

IP-based location is approximate. Platform-redirect analytics shows location by IP geolocation. Mobile carrier traffic often resolves to the carrier’s regional gateway, not the user’s actual location. A scan from a city park might log as the carrier datacenter two hundred kilometres away. Treat platform-level location as a coarse signal, not a heatmap.

The pattern across all these: real scans usually happen, the user often gets where they are going, but the attribution chain has gaps. Build the funnel measurement to handle missing data gracefully and reconcile the two analytics layers explicitly rather than treating either as ground truth.

When you can’t use a dynamic redirect

Sometimes a dynamic redirect is not on the table — privacy policy, vendor lock-in concerns, no budget, no operational owner, or print volumes too high to risk a future vendor shutdown. The good news is that static QR codesA QR code where the destination is encoded directly inside the matrix. Once printed, the destination cannot be changed. Read more → can carry full UTM tracking, because the tracking lives in the URL the code encodes.

The constraint is that you bake the tagging in at print time and cannot change it after the code ships. The strategies that work:

  • Encode the destination with full UTMs. https://brand.com/spring?utm_source=poster&utm_medium=qr&utm_campaign=spring-2026&utm_content=citymall. Keep parameter values short — long URLs raise QR module density and hurt scannability at small print sizes. See the size and print guidelines for the relationship between URL length and minimum print size.
  • Use clean per-placement paths. brand.com/p/spring-citymall. Cleaner-looking, no query string to strip on redirect, but requires you to set up the path on your own domain so the destination resolves. Server logs and any analytics platform that segments by path can do per-placement attribution this way.
  • Pre-decide the URL structure for the entire campaign. A static-only campaign cannot fix tagging mistakes after launch. Spend the planning time at the brief stage, not after the print run.

Static codes are not “untrackable” — they are just less forgiving. Plan the URL once, get it right, and you have full attribution without any platform dependency.

For a stat roundup on adoption and scanning behaviour, QR code statistics covers the broader market context (Mordor Intelligence projects the QR labels market reaching $4.42B by 2030 from ~$3.20B in 2025).

Wrap-up

The whole point of analytics is to make the next decision better than the last. Scan count alone does not let you do that. Build measurement around the funnel — scan, landing, engagement, conversion — and accept that the platform-redirect layer and the landing-page layer will always show slightly different numbers. The gap between them is information, not error. Tag every placement separately, lowercase your UTMs, and validate the full URL on a real device before the print run goes out. If a campaign is dynamic, use the redirect editing for what it is good at: rotating offers behind the same code. If it is static, plan the URL once and ship it; the tracking still works.

Sources

Ready to build your QR campaign?

Apply the same guidance from this article in the generator, then test on real devices before launch.