DEV Community

Cover image for I watched a physiotherapist lose three referrals to a wrong digit
Profile Tap
Profile Tap

Posted on

I watched a physiotherapist lose three referrals to a wrong digit

A physiotherapist I know writes his phone number on the back of every prescription slip. Ten, fifteen times a day. Last month a patient read a 3 as an 8, called the wrong person twice, and went to a different clinic instead.

That is not a marketing problem. It is a data handoff problem, and it has a fairly boring engineering answer that most professionals never get told about.

I have spent the last year building profile infrastructure for exactly this kind of handoff, so this post is about what actually breaks — and what the constraints look like once you try to solve it properly.

The handoff has three failure modes

When a professional gives someone their contact details, the transfer fails in one of three ways:

  1. Transcription error. Handwriting to human eye to keypad. Every hop is lossy. Ten digits with no checksum means a single wrong character produces a valid-looking number that belongs to someone else. There is no error detection anywhere in this pipeline.

  2. Staleness. A printed card is a snapshot. The moment the clinic moves, the number changes, or a new specialisation is added, every card already in circulation is wrong. You cannot patch distributed physical copies.

  3. Partial capture. People take a photo of the card and never open it again. The data never reaches the contact book, which is the only place it would have been useful.

Notice that all three are properties of the medium, not of the person. Printing a nicer card does not fix any of them.

Pointer, not payload

The fix is the oldest trick in systems design: stop shipping the data, ship a reference to it.

Encode a URL instead of the details. The URL resolves to a profile you control. Now:

Transcription error is gone, because nobody types anything.
Staleness is gone, because the pointer is stable and the target is mutable.
Partial capture improves, because the target page can offer a proper vCard download instead of a JPEG of a card.

This is the same reason DNS exists rather than everyone memorising IP addresses. The indirection layer is the whole point.

Where it gets interesting for professionals specifically is what you put behind the pointer, because a doctor, a freelancer and an insurance agent need three different shapes of the same object.

The shape problem

A generic "digital business card" gives you name, phone, email, done. That is fine for a sales rep. It falls apart the moment the professional has a workflow attached.

Three real examples:

A doctor needs clinic address and timings that differ by day, a way to route new patients differently from existing ones, and often a booking link that is not their personal number. What they do not want is their personal mobile propagating to every WhatsApp group in the neighbourhood.

A freelancer needs portfolio links, a rate or scope enquiry path, and an invoice-ready set of details. The contact info is almost secondary to the proof-of-work.

An insurance or real estate agent needs a document handoff — policy PDFs, listing sheets — plus a review link, because their entire pipeline is referral-driven.

So the profile cannot be a flat key-value dump. It needs to be a typed object with per-type field sets and per-type layout. In our model each profile carries a type discriminator, and the renderer switches on it. Adding a new professional category means adding a schema and a template, not forking the app.

Two transports, one target

The pointer needs to get from the professional to the other person. There are exactly two practical transports today, and you want both.

QR works everywhere with a camera. It is printable, it costs nothing, it survives being photocopied onto a prescription pad. Its weakness is that it needs line of sight, decent light, and a person who knows to point the camera at it.

NFC works by tapping. No camera, no aiming, no light. The card contains a passive NTAG chip with no battery — the reader's field induces current in the chip's antenna and it responds. The data is written as an NDEF record, in this case a URI record.

The two constraints developers usually get wrong:

Range is tiny by design. Roughly 4 cm. That is not a limitation, it is the security model. You cannot passively read a card from across the room.
Coverage is not universal. Plenty of budget phones ship without NFC hardware, and on some the antenna is in an unexpected spot so the tap "misses". So NFC can never be the only transport. Every card needs a printed QR as fallback, pointing at the same URL.

Same pointer, two ways to deliver it. If you only ship one, a predictable slice of your users simply cannot receive the handoff.

What the NDEF record actually holds

Keep it minimal. An NTAG213 gives you roughly 144 bytes of usable memory. That is enough for a short URL and nothing else, which is a useful forcing function — it stops you from doing the thing that seems clever and is actually a trap:

Do not encode the phone number directly. A tel: NDEF record works, and it is a mistake. You have just made the card immutable and permanently tied to one number. Encode the profile URL. The number lives behind it, editable.

Same argument applies to QR. A static QR with contact data baked in is a printed artifact you can never correct. A QR that points to a URL is a pointer you can redirect forever.

The part nobody plans for

Analytics on a physical object. Once the card resolves to a URL you control, you can see how many times a profile was opened and roughly when. For a professional that is genuinely useful signal — which conference actually produced enquiries, whether the cards handed out at a clinic reception get scanned at all.

It also raises the obvious question of what you log. Our position is that the profile owner sees counts and coarse timing, not identity, because the person scanning never consented to anything. The scan is the other person's action. Treating it as tracking data would be the wrong default.

If you are building something similar, the summary is short: ship a pointer not a payload, type the profile instead of flattening it, and always give NFC a QR fallback.

We build this as ProfileTap — profiles for doctors, freelancers and agents among other things. Happy to answer implementation questions in the comments.

Top comments (0)