# Measuring offline-to-online conversion with QR codes

> A static QR code gives you sessions by placement, not scans: the difference is people whose page never loaded. Give every placement its own UTM-tagged URL, read sessions as the floor of true scan volume, and use coupon-code redemption as tracking-free ground truth when you need revenue attribution that survives blocked analytics.

Source: https://useqr.app/docs/ecommerce/measuring-offline-to-online-conversion · Last reviewed 2026-08-21 · UseQR is free forever, no signup.

---

## What you can know, and what you cannot

Honesty first, because most vendor material fudges this. With static codes and standard
web analytics, here is the full epistemic position:

**You can know**: sessions that arrived via each code's URL, when, roughly where (IP
geography), on what device, and what they did next, including purchases. That is
attribution by placement, and it is genuinely useful.

**You cannot know**: scans whose page never loaded (dead spots, abandoned before load),
scans by people whose browsers block your analytics, or how many *people* scanned (one
person, three scans). So: **sessions are the floor of true scan volume, not the count.**
A dynamic-QR provider's "scan count" moves the measurement to their redirect server:
closer to true scans, still blind to camera-opens that never followed the link, and it
[couples every printed code to their uptime](/vs/what-happens-when-a-qr-service-shuts-down).
The trade-offs live on [how to track QR scans](/docs/how-to/how-to-track-qr-code-scans).

## UTM-per-placement discipline

The mechanism is boring and the discipline is everything: **every distinct placement
gets its own tagged URL**, so the session stream separates by physical source.

```
example.com/p/kettle?utm_source=qr&utm_medium=packaging&utm_campaign=kt200&utm_content=box-base
```

The [UTM how-to](/docs/how-to/how-to-add-utm-parameters-to-a-qr-code) covers syntax;
the rules that make the data usable:

- **One URL per placement, not per campaign**, box base vs insert card vs
  [shelf label](/docs/ecommerce/qr-code-on-a-shelf-edge-label) vs advert must be
  distinguishable, or you learn nothing about placement.
- **A written naming convention** before the first code ships, `utm_content` values
  like `st042-aisle3` only help if they are consistent for years.
- **Generate variants [in bulk](/bulk)** from a spreadsheet of placements: hand-editing
  URLs is where taxonomies rot.
- Configure analytics per the [Google Analytics guide](/docs/how-to/how-to-use-google-analytics-with-qr-codes),
  and [test-scan every variant](/validate) before print.

## Incrementality: the question behind the question

Attribution says "this order arrived via the shelf code". The business question is
harder: **would that order have happened anyway?** A
[packing-slip code's](/docs/ecommerce/qr-code-on-a-packing-slip) reorders are mostly
non-incremental. Those customers knew where to find you. A cold-audience placement like
[out-of-home advertising](/docs/marketing/qr-codes-in-out-of-home-advertising) is mostly
incremental. Attribution counts both the same.

You rarely need a formal experiment to think clearly here, but where the spend justifies
it, the clean designs are geographic holdouts (run the placement in some regions, compare
sales) and staggered rollouts. What to avoid is the common self-deception: summing
attributed revenue across placements and calling it "QR-driven revenue": much of it
would have arrived by other routes.

## Ground truth without tracking

When analytics is blocked, distrusted, or the conversion happens offline (the scan led
to an in-store purchase), the oldest method is still the most robust: **a redemption
code**. "Scan for 10% off with code SHELF10" (a distinct code per placement) converts
measurement into till data: redemptions are counted by your POS with no cookies, no
JavaScript, no consent banner, and they capture offline conversions web analytics never
sees. The cost is that it measures only discount-motivated conversions and it changes
the offer itself. Design the codes so sharing does not poison the data: placement-coded,
time-boxed offers, per the [coupon-fraud playbook](/docs/ecommerce/preventing-coupon-qr-fraud).

The strongest setups run both: UTM sessions for behaviour and reach, redemption codes
for revenue ground truth, and the humility to remember the gap between them.

## FAQ

### Can you count how many people scan a static QR code?
Not exactly. You can count sessions arriving at the tagged URL, which misses scans whose page never loaded and analytics-blocked visitors. Treat sessions as the floor of true scan volume, and compare placements rather than trusting absolute numbers.

### How do I attribute sales to a specific QR placement?
Give every physical placement its own UTM-tagged URL (box, insert, shelf, poster) generated in bulk from a documented naming convention. Sessions and orders then separate by placement in your analytics.

### What is the most reliable QR measurement method?
Placement-specific redemption codes counted at the till. They need no cookies or scripts, survive blockers, and capture offline conversions, at the cost of measuring only discount-responsive customers and altering the offer.

### Does attributed QR revenue mean the code caused the sale?
No. Attribution records the route, not the counterfactual, a reorder via a packing-slip code would mostly have happened anyway, while cold-placement conversions are largely incremental. Judge placements with incrementality in mind, not raw attributed totals.

## Try it

- https://useqr.app/url
- https://useqr.app/bulk
- https://useqr.app/validate
