One QR Code for Two App Stores: A Tiny Redirect Page
By Nesim Razon, independent Android developer · 2026-11-16
My website has an "Install with QR" button for people who visit from a computer. It used to be simple, because every app was Android-only. Then the apps arrived on the iPhone too, and I had to decide what that button should show. I ended up with one QR code that works for both stores. Here is how it works and what it costs.
The question: what does the button show now?
Until recently the QR code encoded the Google Play address of the app, including a referrer parameter so that Play Console could tell me how many installs came from the QR. With an App Store version, one code was no longer enough, or so it seemed.
I considered four options: two separate QR codes, one image with two codes side by side, tabs that switch between a Play code and an App Store code, or a single universal code. The first three all put a choice in front of the visitor, and the visitor does not know which one is right until they have already picked up the phone.
Why one code is enough
The button is only visible on desktop. In the stylesheet it needs a mouse-like device (hover and a fine pointer) and a window at least 900 pixels wide, so phones and tablets never see it. That means the person who scans the code is holding the very phone that should install the app, and that phone already knows which store it belongs to.
So the code does not need to carry the choice. It only needs to carry an address that makes the choice after the phone opens it.
The redirect page
The QR code points to a short address of the form /go/<app>/ on my site. A small generator script writes that page for every app that exists on the App Store. The page does three things.
First, it reads the user agent. If it contains iPhone, iPad or iPod, the visitor is on iOS. There is one catch: since iPadOS 13 an iPad reports a Mac user agent, so a Mac user agent together with more than one touch point is also counted as iOS. A real Mac has no touch screen, so it is not caught by mistake.
Second, it sends the phone to the right store with location.replace. I chose replace over assigning location.href because it does not leave the redirect page in the history. Otherwise the Back button would return to my page, which would immediately redirect again, and the visitor would be stuck in a loop.
Third, on Android it opens the same Google Play address as before, with the referrer that marks the visit as coming from a QR code. That keeps the install-source breakdown in Play Console working, so I can still see how many installs came from QR codes.
Desktop and no-JavaScript fallback
If the page is opened on a computer, or the browser has no JavaScript, nothing is redirected. The page then shows both official store badges, one for Google Play and one for the App Store, with a link back to the app's page on my site. Nobody gets a blank page, and anyone who shares the short link by mistake still gets something useful.
The page is marked noindex. It exists for scanners, not for search, and I do not want a pile of near-identical pages in search results.
A smaller code as a bonus
The QR code now encodes a short address instead of the long Play URL with its referrer. Fewer characters means a less dense pattern with bigger squares, which is easier for a phone camera to read from a screen, especially a laptop screen at an angle. The generator uses the segno library with error correction level M.
Only where an iPhone app exists
Not every app has an iPhone version. A small JSON file lists the apps that are on the App Store, and only those get a /go/ page and the universal code. Android-only apps keep a direct Google Play QR, with no middle page at all.
A trap in the site build
My website build splits each page into language folders and writes sitemap entries. When I added the new /go/ folder, the build treated it as a normal site page and started producing translated copies and sitemap lines for it. The fix was one word: adding the folder to the list of directories the language build skips, next to folders such as the QR images and badges. A redirect helper should not be in the sitemap at all.
How I tested it, and the downsides
I opened the short address on an Android phone and it opened the Play listing. The scan with an iPhone camera was confirmed too, so both phones have been checked once by hand. It is a small test, not a device lab.
The downsides are honest ones. The automatic choice needs JavaScript; without it the visitor has to tap a badge. And a middle page is one more hop: a short flash of my page before the store opens, and one more thing that could break, although it is a single static file.
Frequently asked questions
Why not show two QR codes, one per store?
Because the QR button only appears on desktop, the phone that scans it is the phone that should install the app. One code and a page that picks the store spares the visitor a choice.
How does the page know the phone is an iPhone?
It checks the user agent for iPhone, iPad or iPod. Newer iPads report a Mac user agent, so a Mac user agent with more than one touch point also counts as iOS.
Do I still see QR installs in Google Play Console?
Yes. The Android target keeps the Play address with the QR referrer, so the install-source breakdown still counts them.
What happens without JavaScript or on a computer?
There is no redirect. The page shows both official store badges so the visitor can choose.
More from the blog
- Why My App Store Link Returned 404 and the Page Showed 2018 Screenshots
- App Store Review Guideline 2.1 "Information Needed": What I Sent
- App Store Screenshots Without a Phone: Robolectric, a Fake Image Loader and a Headless Browser
- Rewriting for Kotlin Multiplatform Without Changing Behavior: Old Code as a Test Oracle
- A Serverless Remote List for "More Games": One JSON File on GitHub Pages
- Debugging an iPhone From Windows Over USB: Screenshots and Logs With Python