MailSignals

Guide

Gmail's image proxy, and why your open count is a lower bound

Gmail fetches every image through its own proxy and caches it. What that hides, what it still reveals, and why an honest tracker labels a proxied open as a lower bound.

What the proxy does

Gmail does not let the reader's browser fetch images in a message. It fetches them itself, through a proxy that identifies itself as GoogleImageProxy, and serves the copy to the page. Gmail turned this on for everyone in 2013 and, at the same time, began displaying images by default, which is the reason pixel tracking works on Gmail readers at all: before that, images were blocked until the reader clicked.

The proxy also caches. Once it has fetched an image for a message, later displays may be served from its cache without touching the tracker's server again.

What it hides

  • The reader's device and browser. The user agent is the proxy's, every time.
  • The reader's network and location. The request comes from Google's address ranges.
  • Who the reader is. A recipient reading in Gmail and the sender re-reading their own Sent copy produce the same request. This is the root of the self-open problem.
  • Repeat reads. A cached image is a read the tracker never hears about. Any count of Gmail opens is at best a floor.

What it still reveals

The proxy fetches when Gmail displays the message to someone, so a proxied fetch outside the delivery window is good evidence that a person opened it in Gmail. That is real information, and it is the commonest open there is: for many senders, most recipients read in Gmail. The honest report is "opened, through a proxy, so the count is a lower bound and we cannot see the device".

Clicks are unaffected. When a reader follows a link they leave Gmail with their own browser, and the redirect sees them directly.

Two Gmail fetches that are not reads at all

Besides the proxy, Gmail itself fetches images in two situations that a naive tracker counts as opens.

  1. +0.6 s Your own view Pixel loaded Your own Gmail loaded the image while showing the copy in your Sent folder. Who: You.
  2. +1.2 s Automated scan Pixel loaded Gmail prefetched the image while indexing the message, rather than a person opening it. Who: Not a person.
  3. +38 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.
Three Gmail fetches of one pixel. Only the third is a person.
  1. The Sent copy rendering directly. Gmail web sometimes renders the copy the sender just composed with a direct fetch carrying a mail.google.com referrer, from the sender's own browser. MailSignals recognises it by comparing the salted hash of the request's network with the one recorded when the message was registered.
  2. Indexing. A fetch with a Gmail referrer that is neither the proxy nor from the sender's network is Gmail processing the message, not a person reading it. It is recorded as an automated scan and never counted.

Why an honest tracker says "lower bound"

Put the pieces together and a proxied open supports exactly this much: at some moment after delivery, Gmail displayed the message to somebody, at least once. It does not support "read twice", "read on a phone", "read in Berlin", or "read by the recipient rather than the sender".

What a proxied Gmail fetch does and does not support
ClaimSupported by a proxied fetch?
Someone displayed the message in GmailYes
It was the recipient rather than youOnly with extra evidence: what was on your screen, or your network
It was opened N timesAt least N; the cache hides the rest
Which device or whereNo
Which recipient, on a group emailNo

MailSignals reports it that way. The verdict is opened (proxied) at confidence 0.90; the tooltip says "through a mail proxy, so the count is a lower bound" when every open was proxied; the detail page's Who line says "the recipient, or you, if you opened this on a device without MailSignals"; and at the strict sensitivity setting, proxied opens are not counted at all.


Related: what an open count means in each situation · the rule table · Apple's proxy, which goes one step further.

Run it in your own project.

One Firebase project, two subdomains, one deploy script. About an hour the first time, and no subscription afterwards.