What a dynamic QR code is
Every QR code is a container for data. In a static code that data is your content — the URL itself, the Wi-Fi credentials, the contact details. The pattern is the destination.
A dynamic code puts something else in the pattern: a short address on a server we run. When someone scans it, their phone asks that address what to do, and the server answers with a redirect to your real destination. The code never changes. The answer does.
That single indirection is the whole idea, and everything a dynamic code can do — editability, scan counts, switching a campaign off — follows from it. So does everything it cannot do, which is mostly to work without us.
How the redirect works
A dynamic code from this site encodes an address of the form
/r/<slug>, where the slug is eight characters drawn from a
31-symbol alphabet. Here is the path a scan takes:
Two details in that picture matter more than they look. First, the only thing
printed is the short link, so the destination can be rewritten at any time
without touching the artwork. Second, that rewritten answer is served with
Cache-Control: no-store, so a browser or intermediary cannot
cache yesterday's destination and send a scanner somewhere you have since
changed.
Slugs avoid characters that are easy to confuse when read aloud or copied by
hand — no 0, O, 1, l or
I — and words that could be mistaken for a system path, such as
api or login, are held back.
What you can change, and what you cannot
You can change the destination as often as you like. Editing is free and unlimited — it is the feature you came for, so metering it would be perverse. You can also pause a code so it stops redirecting, give it an expiry date, and see its scan history.
What you cannot do is equally worth knowing up front:
-
You cannot reuse a slug. Deleting a code retires its slug
permanently. This is deliberate: if a slug were recycled, a stranger's
already-printed code could one day point at somebody else's destination. For
the same reason a deleted code answers
410 Gonerather than404— the address was real and is not coming back. - You cannot change the printed address. Choose a destination freely, but the short link on the paper is fixed for the life of the code.
- You cannot use it anonymously. Creating one requires an account. An anonymous visitor is offered sign-up instead of silently receiving a static code, because the indirection is the point and there would otherwise be nothing to own or edit.
- You cannot shorten the printed link. The slug is generated, not chosen, and it is eight characters — short enough to keep the code sparse, long enough that slugs are not guessable.
Making a link stop working on a date
By default a dynamic code has no expiry and keeps redirecting
indefinitely. When you create one through the generator you can optionally set
an expiry date, up to ten years out. After that moment the link stops
resolving and answers 410 Gone, and it cannot be un-expired by
editing the destination — the expiry is its own state, not a property of where
it points.
There are two honest reasons to set one:
- The offer really does end. A seasonal menu or a competition entry form that should stop accepting scans on a known date. An expired link telling a scanner "this has expired" is a better outcome than a live link to a page that no longer makes sense.
- The code is out of your control. Something printed on a large run, or handed to a distributor, where you want a definite end rather than an open-ended commitment.
Do not set an expiry to feel tidy. A permanent destination with an arbitrary expiry date is a code that will one day stop working for no reason a future reader can reconstruct — and because slugs are never reused, the only fix is a reprint. If you are unsure, leave it off; you can always pause the link later, and pausing is reversible where expiry is not.
A past date is refused at creation rather than silently accepted, because a link that was born expired would look like a bug rather than a decision.
Routing by device
A dynamic link can send different scanners to different places. You add rules, and each rule names a device class and a destination:
| Rule | Sent to | The obvious use |
|---|---|---|
| iOS | The App Store listing | iPhone and iPad visitors get the native app |
| Android | The Play Store listing | Android visitors get the same app from their store |
| Desktop | Your website | A laptop cannot install a phone app, so send it somewhere useful |
This is the thing a static code structurally cannot do. One printed code, three destinations, decided when the scan happens — which is exactly what an app launch needs and what the app store type cannot express on its own.
Three properties are worth knowing, because they are choices rather than side effects:
- Rules never break a scan. A printed code cannot be recalled, so a redirect that fails is worse than one that goes somewhere slightly wrong. If no rule matches — an unrecognised device, an old browser, a crawler — the scan goes to your primary destination. Every path resolves to something usable.
- Rules are validated exactly like the primary destination. A rule is a second destination, so it goes through the same checks: http or https only, no private or loopback addresses, no embedded credentials. A rule that skipped those would be an open redirect wearing a feature's clothes. The scheme is re-checked at serve time as well as at save time.
- Crawlers count as desktop. A bot's user-agent names no phone, so a device rule sends it to the desktop destination — usually what you want, since it means a crawler does not land on a store page.
Rules are edited on the dynamic links page. Changing a rule takes effect on the next scan; nothing about the printed code changes.
Tagging scans for your analytics
A dynamic link already knows it was reached by scanning a code. Campaign tags
pass that knowledge on to your own analytics, so you can separate QR traffic
from every other route to the same page — utm_source,
utm_medium and utm_campaign are appended to the
destination on the way through.
The rules for this are deliberately conservative:
-
Your own tags win. If the destination already carries a
utm_*parameter you set yourself, it is left untouched and no duplicate is added. Twoutm_sourcevalues in one URL is a URL where different analytics tools read different answers. - Applying it twice changes nothing. The tagging is idempotent, so a redirect that is retried or follows a rule does not accumulate parameters.
-
You can switch it off explicitly. An empty
utm_sourcemeans "do not tag this link", which is distinct from never having set one.
These tags describe the campaign, not the person. They carry nothing about who scanned, and they are the same parameters any other marketing link would use.
When a dynamic code is the right choice
The honest answer is: less often than marketing suggests. A dynamic code is worth its dependency when at least one of these is true.
The destination is not final
A menu that changes monthly, a schedule, a landing page you have not built yet. Print once, edit forever.
You are printing a lot of something
Packaging, signage, vehicle livery. The cost of a reprint is the reason the indirection pays for itself.
You need to count scans
Measuring which poster or which shelf actually gets scanned is a legitimate reason, and impossible with a static code.
You may need to switch it off
A promotion with an end date, or something you might have to withdraw. A static code cannot be recalled.
Do not use one for a permanent destination you control: a homepage, a contact page, a Wi-Fi password. You would be adding a dependency in exchange for nothing. The generator produces a static code by default for exactly this reason, and the toggle that changes that is opt-in.
What the scan analytics actually measure
A dynamic code can be counted because every scan makes a request. A static code cannot be counted by anyone, because nothing is ever requested. This is a property of the mechanism, not a setting — so any tool claiming scan counts for a code that encodes its content directly is either using a redirect or guessing.
| What you see | What it means |
|---|---|
| Total scans | Every redirect served, including repeat scans by the same person. |
| Unique visitor-days | The number of distinct visitor/day pairs — one person scanning on three days counts three times, three people scanning the same day count once. It is the honest unit for data that is deliberately not tied to a person. |
| Scans over time | A per-day series, kept as a permanent rollup. |
| Device family | Mobile, tablet or desktop. Not a model, not a browser version. |
| Operating system | iOS, Android, Windows, macOS or other — the coarse split that tells a phone from a laptop. |
| Country | A two-letter country code, supplied by our network. Not a city, not a coordinate, and shown only where the deployment can supply one. |
| Referrer host | The site that sent the scanner, as a hostname only. |
Bot traffic is recorded so it can be excluded: crawlers are counted internally but never added to the number a person reads, and an empty user-agent is treated as a bot because that is far more often a script than a human.
What we deliberately do not store
Scan analytics is where QR services usually collect far more than they need, so it is worth being specific about the limits here.
- No IP addresses. A scan is attributed to a salted, one-way hash — the same mechanism the anonymous free-trial counter uses. The address itself is never written down and cannot be recovered from the hash.
- No full referrer URLs. Only the referring hostname is kept. A referring URL's query string is where search terms live, so discarding it is what stops a scan report from becoming a keyword report about your visitors.
- No user-agent strings. They are reduced to a device family and thrown away.
- No precise location. The country is derived by our network from the connection and handed to us as two letters. We never see or store the address it came from, so there is nothing to refine into a city or a set of coordinates, and nothing that could be re-resolved.
- Nothing that identifies a person. There is no cross-site identifier and no profile; the system cannot answer "what else did this person do?" because it was never built to hold the pieces.
Raw scan rows are pruned after 90 days. The daily totals are written as scans arrive and kept, so a chart of last year still works even though the individual rows behind it are gone. You can also hide the Visits column entirely, which is remembered per browser — useful if you are showing the dashboard to someone else. The Privacy Policy covers this in full.
Printing an editable code
A dynamic code has more data in it than the URL it stands for is short, so it is denser than you might expect. Everything in the QR code guide applies, with three additions.
- Settle the short link before you print. The printed address is the one thing you cannot edit, so plan it as carefully as you would a domain name.
- Give it more room than a static code. A denser pattern means smaller modules at the same printed size. When in doubt, go up a size — the size calculator will do the arithmetic for the distance you have in mind.
- Test the redirect, not just the scan. Confirm the code reaches the right page after you change the destination, on a phone that has never seen the site before.
What happens if a code stops working
This is the part a static code never makes you think about, so it deserves a straight answer. A dynamic code works only while the redirect service answers.
-
A paused or deleted code stops redirecting immediately.
Deleted codes answer
410 Gone; addresses that never existed answer404. The distinction is deliberate — it tells a crawler that the URL is retired rather than misspelled. - If this site went away entirely, every dynamic code printed from it would stop resolving. Static codes would not.
That is the trade in one sentence. If the thought of it is unacceptable for a given code, use a static one — the destination may be fixed forever, but so is the code's ability to work.
How destinations are vetted
A redirect service is an open redirect unless it is constrained, and an open redirect on a well-known domain is a phishing tool. Every destination is therefore checked when it is created and again whenever it is edited — at the point where a mistake can still be reported to a person rather than discovered by a victim.
- Only
httpandhttps. Schemes such asjavascript:,data:andfile:are refused outright, because a redirect to one of those is a payload launcher. - A scheme must be given explicitly.
example.comis rejected rather than guessed at. - Loopback, private, link-local, CGNAT and cloud-metadata addresses are
refused, as are
localhostand.internalnames — this is what stops the redirect being used to probe a network from the inside. - Embedded credentials, control characters and anything over 2,048 characters are refused rather than silently stripped.
The redirect also sends Referrer-Policy: no-referrer, so your
short link does not turn up in the destination site's logs along with every
visitor who arrived through it.
Dynamic vs static, side by side
| Static | Dynamic | |
|---|---|---|
| What is printed | Your content, encoded directly | A short link to our redirect |
| Edit the destination | No — reprint required | Yes, as often as you like |
| Scan counts | Impossible for anyone | Scans, visitor-days, device, operating system, country, referrer host |
| Route by device | Not possible — one address | iOS, Android and desktop can each go somewhere different |
| Works offline | Yes | No |
| Depends on a service | No | Yes — us |
| Account needed | No | Yes |
| Cost here | Free, three without an account | Counts against the same allowance; editing is free |
To create one, use the generator, choose a website link and turn on “Make this link editable after printing”. Codes you have made are managed, edited and measured on the dynamic links page.
Frequently asked questions
Can I change where a QR code points after printing it?
Only if it is a dynamic code. A static code has its destination encoded in the pattern, so changing where it points means printing a new code. A dynamic code holds a short link, so the destination behind it can be rewritten at any time without touching the printed artwork.
Do dynamic QR codes expire?
Not by default. A dynamic code keeps redirecting for as long as the
service resolves it, and editing the destination is free for that whole
time. You can optionally set an expiry date when you create one — up to
ten years out — after which it stops working and answers
410 Gone. Either way it depends on the redirect service
staying online, which is the risk a static code does not carry.
Can a static QR code track scans?
No, and it is worth being sceptical of anything that claims otherwise. A static code contains its content, so a scan is decoded by the phone and never contacts a server. There is no request to count. Scan tracking requires a redirect, which means a dynamic code.
What do you store about the people who scan my code?
A salted one-way hash of the IP address, the referring hostname, a coarse device family, and whether the request looked like a bot. No IP addresses, no full referrer URLs, no user-agent strings, and no way to identify a person. Raw rows are deleted after 90 days; daily totals are kept.
What is a "unique visitor-day"?
One distinct combination of visitor and calendar day. One person scanning on three separate days counts as three; three people scanning on the same day counts as one. It is a deliberate compromise: telling unique people apart would require holding a per-person identifier over all history, and this measurement is not worth that.
Why does a deleted dynamic code return 410 and not 404?
Because the address was real. 410 Gone tells a browser and a
search engine that the link existed and has been retired permanently, where
404 suggests a typo. Slugs are never reused, so a retired link
can never be pointed somewhere new.
Can I use a dynamic code for free?
Creating one requires an account, and it counts against the same free allowance as any other code. Editing the destination afterwards is free and unlimited, because editing is the feature. See the Terms of Service for the current limits.
Can one QR code send iPhone and Android users to different places?
Yes, with a dynamic link and device rules. You can send iOS to the App Store, Android to Google Play and everything else to a web page, all from the same printed code. A static code cannot do this — it carries one address, so every scanner goes to the same place. Rules are set on the dynamic links page and can be changed at any time without reprinting.
What happens if no device rule matches a scan?
The scan goes to your primary destination. That is deliberate: a printed code cannot be recalled, so a redirect that fails would leave the visitor with nothing. An unrecognised device, an old browser, a crawler and an empty user-agent all fall back to the primary destination rather than showing an error.
Can I add campaign tags to a dynamic link?
Yes. utm_source, utm_medium and
utm_campaign can be appended automatically, so your own
analytics can tell QR traffic apart from other routes to the same page. If
the destination already carries a tag you set yourself, yours is kept and
nothing is duplicated.
Should I use dynamic or static for a business card?
Static. A business card points at something you control and expect to keep, and a card is cheap to reprint. The dependency of a dynamic code buys you nothing there. Use dynamic for the cases where the destination genuinely may change or the print run is expensive.