Set Up QR Codes for a Campaign
The problem
You need scannable QR codes for your campaign materials — but a QR code that just points to your homepage is untracked and unmeasurable. This workflow creates fully attributed, print-ready QR codes and confirms your landing page looks correct in search and social sharing previews before anything goes to print.
What you'll accomplish
Tools in this workflow
Follow this workflow in sequence to move from question to decision without losing context.
Step-by-step
Why this workflow works
The UTM step must come before QR generation because the QR code encodes the final URL — if you change the UTM parameters after generating the code, you need to regenerate the code and reprint all materials. The SERP preview step is last because it's a quality check on the destination page, not the QR code itself — but it's important to do before launch because a broken or truncated snippet on social sharing previews undermines the campaign even if the page content is great. Campaigns that skip this step often have QR codes pointing to pages with missing meta descriptions, which shows as blank previews when the URL is shared on WhatsApp.
Frequently asked questions
Do QR codes expire?
Static QR codes (which directly encode a URL) do not expire as long as the destination URL remains live. The QR code itself is just an encoded URL — it's permanent. However, if the URL it points to changes or the page is taken down, the scan will 404. Dynamic QR codes (offered by paid QR services) encode a redirect URL that you can update — these do technically expire if you stop paying for the service. For campaign landing pages, static QR codes with direct UTM URLs are simpler and more reliable.
How do I track who scanned my QR code?
UTM parameters in the embedded URL are the standard method. When someone scans the QR code and their browser opens the URL, Google Analytics (or any other analytics platform) reads the utm_source, utm_medium, and utm_campaign parameters and records the session under those labels. In GA4, go to Acquisition > Traffic Acquisition and filter by your campaign name to see scan-driven sessions, conversions, and revenue. You can also differentiate between multiple QR codes on different physical materials by using unique utm_content values per code.
What size should a QR code be on print materials?
Minimum 2cm × 2cm (about 0.75 × 0.75 inches) for materials viewed at arm's length (business cards, pamphlets). For materials viewed at greater distances (posters, banners, event signage), scale proportionally: at 1 metre viewing distance, 3–4cm; at 2 metres, 6–8cm; at 5 metres, 15cm+. A useful rule of thumb: the QR code size should be at least 1/10 of the viewing distance. High error correction (Level H) allows the code to include a logo overlay while remaining scannable.
What is a SERP snippet and why should I preview it before a campaign launch?
A SERP (Search Engine Results Page) snippet is the title and description text that Google shows for your page in search results. Even for campaign pages primarily driven by paid traffic or offline QR codes, the snippet matters because: people often search for the brand or product after seeing the campaign, Google may show the page in related searches, and the meta description text is also used in social sharing link previews on WhatsApp, Twitter, and LinkedIn. A truncated or irrelevant snippet reduces click-through rate from organic search and looks unprofessional when shared on social.
Can I use the same QR code for a digital and print campaign simultaneously?
Yes — a single QR code encodes one URL and works identically across digital and print placements. But if you want to measure performance separately by placement, create distinct QR codes with different utm_content values (utm_content=digital-banner vs utm_content=print-flyer). This way GA4 can show you which placement drove more scans. The QR codes will look visually identical but encode different URLs. Never use one QR code to serve two different destinations — use separate codes with the same utm_campaign but different utm_source or utm_content.