This is the exact setup for tracking QR codes in Google Analytics 4. It assumes you already know why you'd want this (if not, start with our overview of QR code analytics) and skips straight to the configuration.
Total setup time once you have the basics in place: about 15 minutes for the first QR campaign, 2 minutes for each one after that.
Before you start, make sure:
gtag.js) is installed on every page the QR code can land on. If you're not sure, view the page source on the destination URL and search for your GA4 measurement ID (format G-XXXXXXXXXX).The UTM parameters in your destination URL are what make a QR scan distinguishable from any other visit in GA4. Three are essential, two are optional:
utm_source - the specific physical placement. Examples: table-tent, billboard-broadway, flyer-summer, business-card. Be specific - this is what lets you compare placements.utm_medium - always qr for QR code campaigns. Consistency here is more important than cleverness. It's how you'll filter all QR traffic across every campaign.utm_campaign - the marketing campaign name. Use lowercase + hyphens: summer-menu-2026, product-launch-q3, winter-promo.utm_term (optional) - originally for paid-search keywords. For QR campaigns, use it to track A/B variants if you're running them.utm_content (optional) - useful for distinguishing two QRs in the same campaign with the same source/medium (e.g., front of business card vs. back).You can build these by hand or use the free UTM builder on whew.cc. The builder enforces lowercase + hyphen conventions and prevents the most common typo problems.
Example finished URL for a restaurant table tent campaign:
https://yourrestaurant.com/menu?utm_source=table-tent&utm_medium=qr&utm_campaign=summer-menu-2026
You have two choices, and the right one depends on whether the destination URL might change:
Use any free QR generator - including whew.cc's free static QR generator. Paste the UTM-tagged URL, download the QR as SVG (for print) or PNG (for screen). Print, post, done.
Pros: free, no signup, never expires. Cons: if the destination URL changes, you have to reprint.
Use a dynamic QR generator (whew.cc's free signed-up tier covers this). The dynamic QR encodes a short whew.cc link; you set the redirect to the UTM-tagged URL. The QR can be re-pointed later if the destination URL changes.
Pros: editable destination, free scan-level analytics from the QR dashboard, layered on top of GA4. Cons: free tier expires (90 days for signed-up, 2 weeks for anonymous); paid plan removes this.
Before printing 500 of these, scan your QR with your own phone and verify GA4 sees it:
utm_source / utm_medium values (or "table-tent / qr" in our example).If nothing shows up: (a) check the destination page source for the GA4 tag; (b) check that your UTM parameters survived any redirects (some shorteners strip query strings); (c) check that your browser isn't blocking GA4 via cookie consent or ad blocker - test in incognito mode.
A pageview is good, but a conversion is what justifies the print spend. In GA4:
Standard events GA4 fires automatically that you can mark as conversions: file_download, form_submit, scroll (90% threshold), video_complete. Custom events your site fires can also be marked.
After 24-48 hours, the Conversions report shows conversion rate per traffic source - including your QR campaigns.
Three GA4 reports answer different questions about QR campaigns:
Reports - Acquisition - Traffic acquisition. Default dimension "Session source / medium" splits traffic by source. Filter or search for "qr" in the medium column. You'll see sessions, engaged sessions, average engagement time, and conversion rate per QR source. This is the report you'll check most often.
Reports - Acquisition - User acquisition - First user campaign. Aggregates all QR sources under their campaign name (the utm_campaign value). Useful for asking "how is the summer-menu campaign performing across all its placements?"
Reports - Realtime. Use this when you want to confirm a scan registered immediately (your own test scans, or watching a launch event live).
GA4 sees the destination-side session. The dynamic QR generator (if you used one) sees the redirect-side scan. Together they answer the full lifecycle question:
Discrepancy is normal: scan count from the dynamic QR will typically be 10-30% higher than session count in GA4, because some scanners abandon before the page loads, some block cookies, and some are bots. The gap itself is interesting data - a large gap means scanners aren't reaching your page (or aren't accepting cookies).
QR, qr, and Qr as different mediums. Pick qr and never deviate.utm_source=Table Tent becomes utm_source=Table%20Tent, which then shows up as Table Tent in reports - usable but ugly. Stick to table-tent.qrwhew.cc's free tools cover both ends of this setup: a UTM builder that enforces the conventions above, and a free QR generator (static or dynamic) that encodes the resulting URL. No signup required for static.
UTM builder QR generatorutm_source (the placement), utm_medium (always 'qr'), and utm_campaign (the campaign name). (3) Encode that URL as a QR code (static or dynamic). (4) In GA4 Admin, mark your conversion action. (5) Read Reports - Acquisition - Traffic acquisition, filtering by source/medium to see per-QR performance.gtag.js install captures pageviews with UTM parameters automatically. Google Tag Manager is useful if you want to fire custom events on specific actions (form submits, button clicks, scroll depth) without changing site code, but it's not required for basic QR code tracking.utm_source value. Example: a restaurant with 10 table tents could use utm_source=table-tent-1, table-tent-2, etc., or group them as utm_source=table-tent and rely on the dynamic-QR dashboard for table-level granularity.