Tracker

Privacy

The short, plain version of what we store, who is responsible for it, and how long it lasts. A plain statement below describes what happens today, checked against the running code. Anything marked not enforced yet is something we have committed to but has not shipped — said here so nobody is surprised the day it does.

What this service does

Tracker follows people across three layers: email-open pixels, link clicks, and website activity captured by a snippet installed on a customer's site. Every site the snippet runs on has one of two modes, chosen by the customer:

  • Basic mode (the default). We record people who arrive through a link we tracked for the customer — a link addressed to one named contact, or a link the customer posted publicly. A stranger who clicks a public link is still recorded, with no name and no email attached — see “People we cannot name” below.
  • Extended mode. Also records a visitor who arrives on their own, with no tracked link at all. See “People we cannot name” below for exactly what is stored.

It is not general website analytics: in basic mode, a visitor who arrives with no tracked link, and has never clicked one before, is not recorded at all.

Who is responsible

The account — our customer — decides who to track and why, and is responsible for having a lawful basis and any consent that requires. We are the processor. We do not decide who gets tracked, and we do not use the data for our own purposes.

The honest position is that the customer's own site needs consent, not that none is needed: recognising a returning visitor requires storing a persistent identifier on their device, which sits squarely within ePrivacy Article 5(3), the EU rule governing storage on a visitor's device. There is no audience-measurement exemption for following a named prospect after a cold email.

Extended mode raises the same bar for every visitor, not only the ones who click a link. Once it records data, the customer needs consent from anyone who lands on that site — not just the contacts they emailed.

What is stored

  • A contact: an opaque reference the account gives us. We never learn a name or an email address — the account is the only party that can map the reference back to a real person.
  • Email opens, one row per tracked message, with a coarse verdict (human / proxy_open / prefetch / scanner / unknown) rather than a bare yes or no.
  • Link clicks and website activity — pages visited, active time — recorded for an identified contact when the link or the visit belongs to one, and with no name attached when it does not (a link shared publicly, clicked by a stranger). See “People we cannot name” below for what that second case means and how long it lasts.
  • A network attribution label for some opens — e.g. that a fetch looks like it came from Google's, Apple's, or a corporate scanner's infrastructure — matched in-request against a small bundled list of known provider IP ranges. This is a separate mechanism from the country lookup below and does not by itself produce a country.
  • A persistent identifier, stored in first-party storage on the customer's own site, so a returning visitor is recognised as the same person coming back — whether or not we know their name. This is the piece that needs consent.
  • IP addresses, for link clicks only. We store the address behind a click, in exactly one place (events.ip), because a country alone cannot answer how many different people clicked a link that was shared publicly, or whether the same person clicked it five hundred times. We keep an address for 30 days by default (adjustable per customer, capped at 90 days), then an automatic sweep removes it — see “Retention” below. This does not apply to email opens or to website page views: we have no need for it there.
  • A country, derived from that same click address, using a small offline lookup that never sends the address anywhere else. Like the address itself, this is stored only for link clicks — never for email opens (an address tied to an email open is often a mail provider's or a corporate scanner's own infrastructure rather than the recipient's, which would make a country derived from it actively misleading, not merely unused) and never for page views. Not every address resolves to a known country; when it does not, we simply store nothing for that field.

“Exactly one place” includes our own infrastructure logs, not only the database. The web server in front of this service keeps an access log so a bad deploy can be diagnosed — by default that log records the same visitor address a second time, outside events.ip, outside the retention sweep above, and outside erasure. It is configured to drop the visitor's address before a line is ever written, so the log still exists for diagnosing a deploy, but is not a second place an address lives.

People we cannot name

Not every visit belongs to someone we can identify. This section says plainly what we keep about a person with no name attached, and for how long.

A stranger who clicks a shared link

When someone clicks a tracked link that belongs to no one in particular — one shared in a document or posted publicly — and lands on a site running our snippet, we create a record for them with no name, no email address, and no contact attached. They are identified only by a random token stored in that site's own browser storage. It lets us recognise that the same person came back, without ever knowing who they are.

A visitor who never clicked a link

A customer can turn on extended mode for one of their sites, to additionally record visitors who arrive entirely on their own — no tracked link, no prior visit. The first time someone in extended mode has no identifier already stored, their own browser mints itself the same kind of random identifier described above — entirely on their device, before we ever hear about it. We only start a record for it once that browser reports real activity on the page — a page visited, time spent, how far they scrolled — never merely because a page loaded. From that point on, the pages they visit and how long they spend on them are recorded against that identifier, with no name and no email attached, the same way a stranger who clicks a shared link is recorded. In basic mode none of this happens: a visitor with no tracked link is not recorded, however long they stay on the site.

Turning extended mode off stops this immediately, not only for visitors it has not met yet. The moment a customer switches a site back to basic, anyone who was only being recorded because extended mode was on stops being recorded on their very next visit — we do not wait for anything to expire first. This does not delete what was already recorded about them; retention (below) is what removes that. It also does not affect a stranger who is recorded because they clicked a shared link — that keeps happening in basic mode, on the same site, because it never depended on extended mode being on.

When a stranger becomes a known person

If someone we already hold an anonymous record for later clicks a tracked link that does name a contact, on that same browser, everything they did anonymously becomes attributed to that contact — their earlier page views join their history, under their name.

Be clear about what that means: this data was never truly anonymous. It was collected so that it could later be matched to a name, which is different from data that can never be linked back to anyone. From the moment it is written, it is data that is capable of naming someone — not only from the moment it actually gets matched.

Two things limit how far this reaches, so a shared computer cannot misattribute one person's browsing to whoever next uses it:

  • A time limit. Matching only reaches back 30 days. On its own this is a weak limit — “researched us three weeks ago, then clicked today” and “someone else used this computer three weeks ago” look identical from a clock alone — which is why the next point matters more.
  • One identifier, one person, permanently. Once a browser's identifier is attached to a named contact, it stays theirs. If a different, second person is later recognised on that same browser — a shared computer, a family device — they get a brand-new identifier and a brand-new record. The first person's history is never handed to them, and theirs is never added to it.

We never use an IP address or network to decide that two visits belong to the same person — only the identifier already sitting in that visitor's own browser. An office, a phone network or public wifi can put many unrelated people behind one address; matching on it would attribute a stranger's browsing to the wrong person, with no way for anyone — including us — to tell that it happened.

What we do not store

  • A contact's real name or email address — we only ever hold the opaque reference the account gave us.
  • Any location more precise than the country named above — no city, no region, no coordinates.
  • A country for anything other than a link click — not for an email open, not for a page view.

Erasure

Erasure is genuine, not a flag. Deleting a contact removes every row that carries their reference — messages, links, visitors, nonces, events, website activity — plus the daily rollups tied to their messages and links. Every table that carries a contact's data is required to be covered, and a test enforces it. See the API docs for the actual endpoint.

An audit trail records that an erasure happened and how many rows it removed, keyed by a one-way hash of the contact's reference — never the reference itself.

The honest limit: a record with no name cannot be erased by name. The anonymous records described above — a stranger's visit, not yet matched to anyone — have no contact to erase. “Delete this contact” can never reach them, because there is no contact. Retention is what removes them instead (see “Retention” below). The moment one of these records is matched to a contact, it becomes reachable by that contact's own erasure request, like anything else.

Backups. Nightly off-site backups are planned but not built yet. Today there is no backup, so an erasure is complete and immediate everywhere, with nothing left behind. Once backups exist, an erasure will still reach the live database immediately, but the erased data will persist in the backup until it ages out on its own window — stated here the day that ships.

Opting out

Unauthenticated, and takes the visitor's own persistent identifier. What happens next depends on whether that identifier belongs to a known contact:

  • A known contact. Every identifier belonging to them (one per device) is deleted, so none of their devices are recognised any more, and they are marked opted out. Pixels and links keep working — a tracking pixel breaking in a real inbox is not an acceptable way to honour an opt-out — they simply stop recording anything for that contact from that point on, even under a brand-new identifier.
  • A stranger with no name attached. Their one identifier is deleted, so that browser is no longer recognised. There is no contact to mark opted out; a later visit starts a fresh, unrelated record, like any other new stranger.

Either way, opting out stops future tracking — it does not erase history already recorded. Erasing history needs a contact to erase (see “Erasure” above). See the API docs for how to call it from your own unsubscribe page.

What already happened is not special-cased by opting out — it ages out on the normal clock, not a faster one. An IP address already stored against one of their link clicks survives opting out; only the ordinary sweep removes it, 30 days by default and adjustable per customer, capped at 90 (see “Retention” below). For a known contact, their past page views, clicks and opens stay attributed to them the same way, under the same retention policy as anyone else's history — including the gap noted below that it is not yet enforced in code for raw events.

Retention

WhatKept forRemoved by
Raw events (opens, clicks, page views) belonging to a contact13 months, by policyNot enforced yet — today they are only removed if and when the contact is erased.
Daily rollups (per message, per link)Same as the events aboveAlready works — removed immediately when the contact is erased, via the same mechanism.
Account-wide totals (no contact in them)Kept foreverNot personal data — nobody to remove.
Anonymous records (no name attached — see "People we cannot name")30 days by default, adjustable per accountAlready works — an automatic sweep removes them.
IP addresses (link clicks only — see "What is stored")30 days by default, adjustable per customer, upper limit 90Already works — an automatic sweep removes it.
The identifier that recognises a returning visitor (see "What is stored")180 days by default, adjustable per account — but read the next column before relying on itNot enforced by us. We hand the browser that date and ask it to forget its own copy, and it does. Nothing on our side checks it: a copied or modified identifier keeps being recognised. Our own record of one goes with the anonymous records above if no name was ever attached to it; once a name has been, only erasing that contact removes it.

Retention length for the events and rollups above is a per-account setting (accounts.retention_days), because a processor acts on the controller's documented instructions rather than choosing this unilaterally.

The identifier window is accounts.identity_ttl_days, and it governs only the last row above — not the events, not the rollups. It is stated as unenforced rather than quietly listed as a window, because the difference is the whole point: a person who was identified once can stay recognisable indefinitely.