Last October our shop switched to its autumn and winter menu and printed the ordering QR code on kraft paper table stickers. The design looked great: dark brown background, cream code modules, the shop logo embedded in the middle. The printer produced 88 stickers and we put one on every table. At the first dinner rush I tested three phones: two gave no response at all, and the third only worked after holding it at a strange angle for a while, landing on the home page instead of the menu. Over those three days the dashboard counted only 4 customers who scanned and ordered, a conversion rate below 0.2% for the table sticker channel. Only after the reprint did I break down what "it scans" actually means.
1. A code that will not scan is usually one of three things
A QR code is a set of black and white modules plus three finder patterns. The camera has to locate the finder patterns, sample each module, then use the error correction data to recover whatever it could not read. If any part fails, the symptom is always the same: you point the phone at it and nothing happens.
- Not enough contrast: the brightness difference between foreground and background is too small. Light modules on a dark base are inverted, and most phone cameras recognize them far less reliably than dark modules on a light base. Pale gray on white is another design favorite: it looks refined to the eye and reads as a blur to the machine.
- Modules too small: shrink the printed size, or pack in too much content so the module count explodes, and a single module ends up under 0.5 mm on paper, which the camera cannot sample accurately. Scaling the same artwork down to business card size is the easiest way to hit this.
- Centre covered: a logo or text sits on top of key modules, and once it exceeds the correction capacity the code cannot be read at all. Coverage over any of the three finder patterns fails immediately.
2. The error correction level sets how much area a logo can eat
A QR code has four redundancy levels, L, M, Q and H, with clear tolerances for damage:
| Level | Recoverable damage | Good for |
|---|---|---|
| L | about 7% | On-screen display with no coverage |
| M | about 15% | General use |
| Q | about 25% | Possible wear, lamination, light coverage |
| H | about 30% | The level to use when a logo sits in the centre |
So the question of whether a logo hurts scanning has a definite answer: keep coverage under 30% with enough redundancy and it is fine, but force a logo into the default level and it will fail. Our first version used the default level together with a logo covering nearly a quarter of the code, hitting both limits at once.
3. The order in which I redid it
- Shorten the content first. The original encoded a full block of menu copy plus a long link with a pile of parameters, which doubled the module count. After switching to a short link the code became one step less dense, and the modules grew noticeably at the same sticker size. That was the cheapest step and it needed no design change.
- In the QR Code Generator I set error correction to H, used a near-black dark gray for the foreground, kept the background pure white, left the quiet zone free of any text, and reduced the logo to about one fifth of the code area.
- For brand feel, change only the foreground: a linear gradient from dark to light along a single direction is safe, and we ended up with dark gray to ink green. Switching the background to red or gold is the riskiest move, so do not bother trying it.
- Do not skip self-testing. After generating the code I uploaded the image to the QR Code Decoder to confirm the content and type matched the link I intended, then scanned it with three different phones, two Android and one iOS, at 30 cm and 80 cm.
- Always export SVG for print and let the printer produce the final piece at 8x8 cm instead of enlarging the designer's PNG. The smallest sticker I would make is 3x3 cm; below that I would not put a code on it at all.
4. Content length sets the density, and the minimum print size
Two codes of the same physical size: the more characters they hold, the denser the modules and the smaller each module on paper. I now treat content length as the first constraint when choosing a format:
| Encoded content | Approximate characters | Modules at level H (approx.) | Suggested minimum edge |
|---|---|---|---|
| Short link redirect | around 30 | 33x33 | 3cm |
| Campaign link with parameters | 60-80 | 45x45 | 4.5cm |
| A full block of menu copy | 150 or more | 65x65 | 7cm |
| Business card details (name, phone, email, address) | around 200 | 73x73 | 8cm |
There is one rule behind it: a single module should not be smaller than 0.5 mm on the finished paper, leaving the camera room to focus. At 3x3 cm a sticker carrying a short link is fine. If you insist on a full block of menu copy, you need 7 cm or more, and a 7 cm code on a table is already large enough to cover the dish names. The right fix in that case is not a bigger sticker but different content: move the copy to a landing page and let the code just point the way.
One more maintenance lesson: a static code cannot be changed once printed, so anything that may change belongs on the landing page side. We ended up pointing the stickers at a fixed address with no campaign parameters, so each season we only edit the page, and those 88 stickers have not been reprinted since.
5. Details that are easy to overlook
- The quiet zone is not decoration: that white ring is what the camera uses to find the boundary. Trimming it for a tighter look clearly raises the failure rate, so treat it as part of the code.
- A static code has no expiry and cannot be edited: the content is burned into the pattern. Redesign the landing page, end the campaign or lose the short link service and the printed code is dead. Before a large print run, confirm who will maintain that link long term.
- Materials swallow contrast: glossy lamination, brushed metal plates and dark wood all cause recognition failures regardless of the design. Moving to a matte laminate dropped the failure rate a lot with the same colors.
- One code per item costs labor: giving every product its own code means generating and checking each one. Dozens are manageable; with hundreds you need a batch generation and inspection process first.
- Never encode sensitive information: put an admin URL, an internal path or an account name in a code and anyone who scans it has it. When sharing WiFi, hand out the guest network only, never print the main password at the door.
6. Common questions
Q: Does adding a logo really affect scanning?
It depends on the covered area and the correction level. At level H, a logo within about 20% of the code area that avoids the three finder patterns made no difference in my tests. At level L, any logo sharply raises the failure rate.
Q: Should I send SVG or PNG to the printer?
Use vector for print, roll-up banners and packaging so it stays sharp at any size. PNG is enough for web and chat images. If you must send PNG, the original pixels should be at least three times the finished dimensions.
Q: Why does a colleague's phone scan it when mine does not?
Focus and decoding differ a lot between camera implementations, especially at low contrast. Do not validate a whole print run with one phone; cover at least two or three models and two distances.
Q: Can I check where an already printed code points?
Yes, if the image is clear. Upload it and you can identify the type, such as a link, plain text or WiFi settings. Checking whether a batch was printed correctly is cheaper than peeling the stickers off and reprinting.
Q: Are color codes more likely to fail than black and white?
The problem is not color but brightness difference. With a dark enough foreground and a light enough background, color scans fine. If the two colors are close in brightness, no palette will save it.
Reprinting that batch of stickers cost a bit over two hundred, far less than three days with only four successful scans. My acceptance criteria are now down to three: error correction at H, dark modules on a light background, and vector for print. A code on physical material is an interaction entry point, not decoration. Review it like an entry point and this kind of failure stops happening.