Maildriply
All posts
2 min readby Maildriply Team

How Gmail open tracking actually works (and where it lies)

A practical breakdown of email open tracking inside Gmail — the pixel, the image proxy, deduplication, and the bot heuristics that determine whether an open is real.

engineeringgmailtracking

Open tracking is the oldest trick in email analytics. It's also the most misunderstood. Every "open rate" you've ever seen is the output of half a dozen heuristics fighting over what counts as a real human glance at an inbox. This post explains what we actually do, and where the model leaks.

The naive version

You drop a 1×1 transparent PNG into the bottom of an HTML email. The image src points to a URL on your server. When the recipient's mail client renders the message, it fetches the image. You record the fetch as an "open."

That works for about thirty seconds, until you remember Gmail exists.

Gmail's image proxy

Gmail does not fetch images from the recipient's IP. It fetches them from Google's servers, caches the result, and rewrites the src to point at googleusercontent.com. This is great for the user — no third party sees their IP address — and miserable for naive trackers, because:

  1. The fetch happens at delivery time, not at open time.
  2. Every recipient looks the same — same IP range, same user-agent.
  3. The image stays cached, so subsequent opens from the same recipient don't always reach your server.

If you record every proxy fetch as an open, your open rate is wrong in both directions: inflated, because Gmail's proxy fetches even unopened mail, and deflated, because cached opens never come back.

What we do at Maildriply

Three rules, in this order:

  1. Sign the pixel token. Each pixel URL embeds an HMAC-SHA256 token keyed to (recipientId, messageId, signedAt). A forged or replayed request fails token validation in constant time and is dropped.
  2. Fingerprint the proxy. Google's image proxy has a stable User-Agent (GoogleImageProxy), a known IP range, and a pre-fetch fingerprint: it fetches all images on the message at once, typically within seconds of delivery. We discard requests that match any two of those signals.
  3. Deduplicate per recipient. One human equals one open, regardless of reloads, multi-device viewing, or proxy cache misses. We use a bounded LRU per recipient with a sliding window.

The result is an open rate that trends correctly between campaigns even though no individual open is provably real.

Open rate is a relative signal

Treat open rate as comparative, not absolute. Campaign A vs campaign B is informative. "62% of my recipients opened this" is a story you tell yourself.

When the model breaks

Several edge cases still bite us:

  • Apple Mail Privacy Protection pre-fetches images at delivery and hides the recipient's IP. We treat MPP fetches as a soft "delivered" signal rather than a real open.
  • Image blockers mean some real opens never reach us at all. Click rate is the safer indicator of intent.
  • Newsletter clients like Spark or Hey have their own proxies and fingerprints. We update the heuristic set as new ones appear.

If you want the gory implementation details, the source is open: see backend/src/modules/tracking/recordOpen.ts. Pull requests welcome.

Keep reading