Blog · · QR Agent
A QR code on a patient intake form is a log of who visited your clinic
Put a QR code on the paperwork you hand a patient and you have built two things. The first is the one you meant to build: a form, on their phone, instead of a clipboard. The second is a record, on somebody's server, of who scanned a code that exists only inside your clinic.
The second one is the problem, and almost nothing written about QR codes in healthcare mentions it.
What the scan record actually contains
A dynamic QR code resolves through a server. That is what makes it changeable, and it means every scan is a request: an IP address, a user agent, a timestamp, and the identity of the code that was scanned. Take a code that exists only on the intake form at one clinic, and the rest follows. A row saying "someone at this address opened the intake form for this practice at 14:12" is not anonymous. It is a health-adjacent fact about a person, generated as a side effect of a convenience.
Most QR platforms treat this as a feature. Scan analytics is the thing they sell.
What we do about it
Two separate mechanisms, because they answer different questions.
Addresses are never stored raw. Every viewer IP on this platform is stored as a keyed HMAC rather than in plaintext, and never as a plain SHA-256 either — the IPv4 space is small enough to reverse a plain hash by brute force in seconds, which makes an unkeyed digest a decorative measure rather than a real one. With the key, unique visitors are still countable. Without it, the stored value does not lead back to an address.
For this case, you can turn scan recording off entirely. Per code. The patient intake starter ships with it off by default, because a hashed record you did not need is still a record you now have to reason about in a data-protection assessment. No row is written at all — not a hashed one, not a truncated one.
The gate is a private link rather than an account. Asking a patient to create a login to read the instructions they were handed in person is a barrier that produces exactly one outcome: they do not read the instructions.
Where the guarantee ends
This is the part most pages skip, so:
The person who opens it sees it. The form content is encrypted at rest, sealed to that one code and that one workspace. It is not protected from the patient you sent it to, and anything on their screen can be screenshotted, forwarded or left open on a shared phone.
The title is not the content. Titles, folder names and campaign labels are metadata, readable by anyone on your team with access to the dashboard. "Oncology intake — J. Smith" in a title defeats the encryption underneath it. Put nothing in a title you would not write on the outside of an envelope.
Turning off scan logging turns off scan logging. You will not know how many people opened the form, because that is the point. If you need the count more than you need the silence, that is a legitimate choice — make it deliberately, per code, rather than discovering afterwards which one you got.
Your own infrastructure still sees the request. We are not the only hop between a patient's phone and this server. A network operator sees a connection to our domain; what they do not see is which code, because the path is opaque and the gate pages send no referrer.
The honest summary
A QR code on an intake form is a good idea. The default implementation of one is a visitor log you did not intend to keep, and it takes two specific decisions — a keyed hash for addresses and an explicit off switch for recording — to make it not be that.
Start from the patient intake template and both are already set.