What scan analytics can — and cannot — capture
QR analytics works because a dynamic code routes every scan through a redirect server, and that server can observe the request before forwarding it. From a single HTTP request it can record: the timestamp, the approximate location (from the IP address, usually city-level), the device family and operating system (from the user agent), and which specific code was scanned.
Be equally clear about what it cannot capture. It does not know who the person is, their name, or their phone number. It cannot see what they do after the redirect — time on page, purchases, and sign-ups belong to your website analytics, not the QR layer. And it never sees scans of static codes at all, because those never touch a server.
A subtlety worth knowing: some phones and messaging apps pre-fetch links before the user actually opens them, which can register phantom "scans". Good analytics platforms filter known bot and preview traffic, but treat single-digit differences as noise, not signal.
Unique vs total scans: two numbers, two questions
Total scans answers "how much is this code used?" — every scan counts, including the same person scanning the menu at lunch and again at dinner. Unique scans answers "how many different people did this reach?" — repeat scans from the same device within a window are collapsed into one.
The ratio between them is often the most interesting number. A poster code with 500 total and 480 unique scans reached many people once — classic awareness. A menu code with 500 total and 120 unique means people come back to it repeatedly — engagement. Judge a placement by the metric that matches its job: unique scans for reach campaigns, totals for utility codes like menus and schedules.
Because QR tracking is cookieless (more on that below), uniqueness is estimated from anonymized request fingerprints rather than tracked identities — accurate enough for decisions, by design not perfect for surveillance.
Geo, device, and time: reading the breakdowns
Time-of-day and day-of-week patterns are the fastest to act on. A café code that peaks at 8 am and 1 pm tells you when to rotate the featured item. A conference banner that spikes during coffee breaks tells you when the booth needs staff. Overlay scans on your own operating hours and the anomalies point at real-world causes.
Geo data is city-level, derived from IP — precise enough to compare a Riyadh campaign against a Jeddah one, or to discover that a code printed on export packaging is being scanned in markets you never targeted. Device breakdowns (iOS vs Android, phone vs tablet) matter most when the destination differs by platform: a heavy iOS skew argues for polishing the App Store path first.
These same dimensions can also drive behavior, not just reporting: with smart routing rules, one printed code can send Android users to Google Play, route scans by country to localized pages, or serve a different destination after business hours. On Qrindo, the same device/time/geo signals that power the analytics also power the routing rules.
UTM forwarding: make QR traffic visible in your web analytics
Scan analytics ends at the redirect; your web analytics begins at the landing page. UTM parameters are the bridge. Append tags like utm_source=qr, utm_medium=print, utm_campaign=summer-menu to the destination URL, and Google Analytics (or any web analytics tool) will attribute the session — and everything after it, including conversions — to that specific QR campaign.
The catch with redirect-based codes: the redirect must actually forward those parameters to the final destination, and preserve any parameters added at scan time as well. Check that your provider does this — Qrindo forwards UTM and other query parameters through the redirect untouched, so campaign attribution survives the hop.
Adopt a naming convention before you print: one utm_campaign per campaign, one utm_content per placement variant ("table-tent" vs "window-sticker"). Attribution reports are only as clean as the tags you committed to on day one.
Turning data into placement decisions
The cardinal rule: one code (or at least one distinct short link) per placement. If the flyer, the window sticker, and the counter card all share one code, their numbers merge into an unanswerable average. Separate codes turn "is QR working for us?" into the far better question "which placement is working?"
Then run cheap experiments. Move the lowest-performing code to a new spot for two weeks and compare. Test eye-level versus counter-level, entrance versus exit, with a call-to-action line versus without. Because dynamic codes are editable, you can even A/B the destination itself — same poster, two landing pages — and let scan-through behavior pick the winner.
Review on a fixed cadence — monthly is enough for most businesses. Kill or move the bottom placements, double down on the top ones, and write down what you changed and when, so spikes in the chart have explanations attached.
Tracking that respects the person scanning
QR analytics does not need to be creepy to be useful. Everything described above — counts, geo, device, time — works from anonymous, aggregate request data. There is no need to plant cookies, fingerprint browsers, or build advertising profiles of people who just wanted to see a menu.
This is Qrindo’s stance by design: IP addresses are hashed rather than stored raw, no tracking cookies are set on the person scanning, and analytics stays at the aggregate level. You still get every chart this guide describes; the individual stays anonymous. With privacy regulation tightening across the GCC and EU alike, "we never had the raw data" is also the safest compliance posture there is.
One operational note: retention matters as much as collection. Know how long your provider keeps scan events — Qrindo retains 365 days of scan history, enough for full year-over-year seasonal comparisons.
Getting the data out: CSV, webhooks, and the API
A dashboard is where analysis starts, not where it ends. For monthly reports, board decks, or a pivot-table session, export scan data as CSV — per code or across the account — and slice it however your spreadsheet allows. Enriched columns (city, device, referrer code) save you the joins.
For real-time needs, webhooks invert the flow: instead of you polling for data, the platform calls your endpoint the moment a scan happens. That enables live event counters, instant Slack alerts when a flagship campaign goes quiet, or feeding scans straight into your own data warehouse.
And when QR data needs to live inside your own product — a client dashboard, an internal BI tool — a REST API closes the loop. Qrindo exposes codes, links, and scan analytics over a REST API with OAuth2 and webhooks, so "export" can mean "integrated" rather than "downloaded".