Self-hosted · open source · no Gmail permission
Honest email tracking for Gmail, hosted by you.
See when the email you send is opened, clicked, replied to or bounced, with the reason behind every verdict. MailSignals runs in a Firebase project you own and never asks for access to your mailbox.
- No Gmail OAuth scope, ever
- Your data in your Firebase project
- Your own tracking domain
- MIT licence, 371 unit tests
- ✓✓ Ada Lovelace Proposal: analytics engine, phase two — Attached the revised scope and the numbers we discussed 10:42 Opened twice · last 14 minutes ago · through a mail proxy, so the count is a lower bound
- ↩ Grace Hopper Re: Compiler talk on Thursday — Yes, 3pm works. I will bring the slides 09:15
- ↗ Noor Haddad Onboarding checklist for the pilot — Everything you need is in the doc linked below Yesterday
- ✓✓ Kenji Sato Invoice 0142 — Payment terms as agreed, 30 days Yesterday
- ✓ Priya Raman Quick question about the API limits — Before I commit to the batch size Mon
- ✕ ops@oldvendor Renewal — Following up on the quote from March Mon
Why it exists
Commercial trackers ask for your whole mailbox. This one asks for nothing.
They need the full Gmail scope because they rebuild group emails and rewrite your Sent copy through the Gmail API. MailSignals does everything inside the Gmail page instead, through the InboxSDK library, so sign-in asks for openid, email and profile and stops there.
| Commercial trackers | MailSignals | |
|---|---|---|
| Gmail OAuth scope | Full mailbox access | None |
| Google verification | Annual CASA Tier 2 security assessment | Not required |
| Where your data lives | Vendor's servers | Your Firebase project |
| Tracking domain | Shared, on every blocklist | Yours alone |
| Cost | $36–72 per user per year | About $0–3 a month, mostly the domain |
The differentiator
Every number is defensible in one sentence.
A pixel request tells you far less than a green tick implies. Gmail fetches every image through a proxy. Apple downloads images on delivery, before anyone reads. Corporate gateways follow every link. Your own Gmail fetches the pixel too.
So every recorded hit gets a verdict from a 15-rule classifier, a confidence, and a plain-English reason that is shown as body text next to the event, followed by a "Who" line. An Apple prefetch is called a prefetch. A proxied open is called a lower bound. An unrecognised client is recorded and counted nowhere.
Replies beat clicks beat opens, and the interface is built to say so.
The rules, in order, with their confidences →- +0.6 s Your own view Pixel loaded Your own Gmail loaded the image while showing the copy in your Sent folder. Who: You.
- +3 s Delivered, open unconfirmed · 80% sure Pixel loaded Apple Mail Privacy Protection downloaded the image on delivery. The message reached the device, but we cannot tell whether it was read. Who: Nobody yet: the recipient's mail app fetched it on delivery.
- +14 min Opened (proxied) Pixel loaded Gmail loaded the image through its proxy while showing the message. Gmail hides the reader's device and location. Who: Gmail hides who read it. The recipient — or you, if you opened this on a device without MailSignals.
- +1 d 3 h Opened Reply received A reply arrived in this thread. Who: The recipient, on their own device.
How it works
Nothing changes about how you send. Three things happen underneath.
You press Send
The extension plants a 42-byte pixel, linkifies URLs you typed as text, signs eligible links through your own tracking host, and registers the message with your project before Gmail acknowledges the send. If any of that fails, the mail goes out unchanged.
Someone opens it
Their client fetches the pixel or follows a link. The endpoint answers first and records second, classifies the request against what it knows about proxies, prefetchers, scanners and you, and writes an event with its reason.
You find out
A green tick in Gmail within a minute, a desktop notification if you asked for one, a daily digest if you prefer, and a dashboard that shows the whole history with every verdict justified.
Features
What it does, and what it refuses to claim.
Open tracking
A 42-byte pixel per message, shown in Gmail as checkmarks, and counted only when a person was plausibly behind the fetch.
Read more →Honest classification
Every hit gets a verdict, a confidence and a one-sentence reason. An Apple prefetch is called a prefetch, not a read.
Read more →Self-open suppression
Your own reads of your Sent folder are recognised and withdrawn, on desktop, without touching the Gmail API.
Read more →Link tracking
HMAC-signed redirects on your own domain, typed URLs included, with scanner clicks kept but counted separately.
Read more →Replies and bounces
A reply on a tracked thread and Gmail's own delivery-failure notice, both read from the Gmail page.
Read more →Alerts and digest
First open, clicks, replies, bounces, hot threads, revived threads and follow-ups, as desktop notifications, Gmail toasts or a daily email.
Read more →Dashboard
Open and reply rates, a best-time-to-send heatmap, per-contact engagement, and a timeline that justifies every verdict.
Read more →Agent API and MCP
Mail an AI agent sends through the Gmail API gets the same tracking, with every policy decision still made server-side.
Read more →The hardest problem
It does not turn green when you open your own Sent folder.
The most common complaint about every tracker on the market. When you look at a sent message, your Gmail fetches the pixel through the same proxy a recipient would use: same user agent, same IP, same referrer. Nothing in the request tells the two apart.
MailSignals knows two things the request does not say: the extension can see what is on your screen, and the message was registered from your network. Any pixel hit within 20 seconds of you viewing the message is withdrawn as your own, in whichever order the two arrive, with a trigger-side backstop for the race in between. A direct fetch from your own network with a Gmail referrer is recognised without any of that.
On a phone without the extension the ambiguity is real and the product says so: the dashboard offers "That open was me", and after two of those it points you at the one setting that removes the problem at the source.
The four paths, and the one that only appeared in production →Desktop notifications, filtered by your preferences and quiet hours, computed in your timezone rather than the machine's. An alert that fires on a scanner's fetch would teach you to ignore alerts, so only counted events can raise one.
Privacy
Never the body. Never a full IP address. Never a third party.
The people who open your email did not install anything and did not agree to anything, so what is kept about them is the minimum that still lets the classifier work.
- A timestamp, the user agent, an IP truncated to a /24 and a salted hash of it. The full address exists only as a local variable in the request handler and is never written.
- No location, even though a setting for it exists; no code path records one today, and the privacy page says so.
- For mail sent from Gmail in a browser, the body is never read, transmitted or stored.
- Nothing is sent anywhere but your own Firebase project and Google itself. The one third-party library is loaded with its telemetry switched off.
- A do-not-track domain list, an optional disclosure footer and a per-message off switch, so you can comply with ePrivacy and the CNIL where you must.
Notes for the morning: the numbers are in the shared sheet and the summary is below.
Cost
Free software. About the price of a domain to run.
- The software. MIT licence.
- $0
- A month to run, almost all of it the domain
- $0–3
- For a first deployment, mostly waiting for DNS
- 1 h
- End-to-end checks against production, all green
- 240
One Firebase project on the pay-as-you-go plan, whose free quotas cover a person's email with room to spare. No seats, no tiers, no history cap. The bill, line by line →
Questions
The five people ask first.
Why does it not just use the Gmail API?
Because a Gmail scope is a restricted scope. It triggers Google's OAuth verification, an annual third-party CASA security assessment, and a hard cap of 100 lifetime users until that completes. For a tool you host yourself that price buys nothing: everything it needs is on screen in front of you already. The trade is that replies, bounces and your own reads have to be recovered from the page, which is most of what makes MailSignals interesting.
What do the checkmarks mean?
Grey ✓ is sent. Green ✓✓ is opened by a person, as far as the evidence supports. Amber ✓✓ is delivered to Apple Mail, which loads images before anyone reads. ↗ is a link clicked, ↩ is a reply, ✕ is a bounce. Hover any of them and the tooltip says what is known and, when the answer is uncertain, why.
How much work is self-hosting?
About an hour the first time, mostly waiting for DNS and certificates. You create a Firebase project, point two subdomains at it, create an OAuth client and two secrets, run one deploy script, and load the extension. The guide on this site walks through every step and the troubleshooting table covers what usually goes wrong.
Can other people on my machine end up in my history?
No. A browser can hold several Gmail accounts, and the extension runs in all of them, so only a Gmail address you have explicitly linked to your MailSignals account is tracked. The server refuses everything else before writing anything.
Is there a catch?
Two honest ones. Reply detection reads the Gmail page, so a reply on a thread you never open can be missed; there is a manual mark for that. And on a phone without the extension your own reads of your sent mail look like a recipient's, so Gmail's "ask before displaying external images" setting is the real fix. Both follow directly from not having a Gmail scope.
Run it in your own project.
One Firebase project, two subdomains, one deploy script. About an hour the first time, and no subscription afterwards.