When someone opens getapproute.com/your-app, four things happen before their browser finishes its little URL-bar animation. The request hits the closest edge POP. A worker reads the link config out of a tiered cache. It runs the User-Agent, Client Hints, country, and any targeting rules through a small matching engine. It writes a 302 back to the device. End-to-end, the median is under 50 milliseconds.
01What you configure
Every AppRoute link has three required destinations and a list of optional rules. The three required URLs are Android, iOS, and fallback — what desktops, smart TVs, and the occasional Linux laptop will see. That is the default routing table.
- Android URL — usually a Play Store listing, sometimes an APK on your CDN.
- iOS URL — App Store, TestFlight, or an enterprise distribution page.
- Fallback URL — your marketing site, a waitlist, or a desktop download.
On top of that, you can layer targeting rules. Each rule matches one or more of: country, OS, device type, and language. The rules are priority-ordered and the first match wins, then we fall back to the standard Android / iOS / fallback URL. So a Brazilian iPhone with a pt-BR Accept-Language can be sent to a localised App Store URL while everyone else gets the global one — without you running multiple links.
02What we read on the request
We try to read as little as possible, and we never load JavaScript on the client to do it. Everything happens server-side on the redirect itself. The signals we use, in order:
- User-Agent. Classified into one of Android, iOS, iPadOS, macOS, Windows, Linux, ChromeOS, bot, or unknown.
- User-Agent Client Hints when the browser sends them (
Sec-CH-UA-Platform,Sec-CH-UA-Mobile). These are more honest than the UA string on modern Chromium. - Edge geo headers for country and region. We never look at the raw IP — only the geo header our edge already resolves.
- Accept-Language, used only when a rule matches on language.
- Referer, captured into analytics but not used for routing.
We do not store the raw IP address, ever. We hash it with a server-side salt for rate limiting on password gates and that is it. Routing reads the geo header your edge already produced, not the IP itself.
03Why it is a real 302
Plenty of shorteners on the market resolve via a landing page with a JavaScript redirect. We do not. Three reasons:
- It is faster. A native 302 is one round trip and zero render work. A JS redirect is a parse, an execute, and a second navigation.
- It is more honest. The address bar shows the destination URL immediately. Users on shared devices, paranoid security teams, and your own QA can verify where the link goes.
- It survives in-app browsers. Instagram, TikTok, and X all have their own WebViews that handle 302s consistently. JavaScript redirects sometimes do not.
04What happens when a chat app fetches your link
Slack, iMessage, Facebook Messenger and the rest all fetch links before a human ever clicks them — to render a preview card. If we 302'd those crawlers to the App Store, the preview would either fail or show some Apple boilerplate. So we detect them and serve a tiny HTML page with your og_title, og_description, and og_image_url instead. Real users still get the redirect.
The redirect is the only piece any of our users can blame on us. Everything else on the page can hide behind a spinner — ours cannot.— Internal post-mortem · Mar 14 2026
05Numbers, briefly
Here is what 90 days of production traffic looks like across the global edge:
If you want to see this in action, create a free link, point Android / iOS / fallback at different destinations, then open the Test routing panel in the dashboard. It runs the same matcher we use in production against synthetic requests, so you can verify each branch before you ship.