How tracking works
Email Tracker uses invisible 1x1 pixel images embedded in outgoing emails to detect when recipients open messages. The tracking system consists of three main components:
Token generation - Creates unique tracking identifiers
Pixel injection - Embeds tracking pixels in compose dialogs
Open detection - Records opens when pixels are requested
Token generation
When you compose an email, the extension generates a unique tracking token containing metadata about the message.
Token structure
Tokens are compact, URL-safe base64-encoded JSON arrays:
// Token payload format (server/src/background/serviceWorker.js:352-363)
const compactPayload = [
payload . user_id , // Stable user identifier
payload . email_id , // Unique message UUID
payload . recipient , // Recipient email address(es)
payload . sent_at , // ISO timestamp
payload . sender_email // Sender email (optional, for suppression)
];
Token encoding process
The extension encodes tokens in the background service worker:
// extension/src/background/serviceWorker.js:21-37
const userId = await ensureUserId ();
const emailId = crypto . randomUUID ();
const sentAt = new Date (). toISOString ();
const recipient = ( message . recipient || "unknown" ). trim ();
const senderEmail = String ( message . senderEmail || "" ). trim (). toLowerCase () || null ;
const token = encodeTrackingToken ({
user_id: userId ,
email_id: emailId ,
recipient ,
sender_email: senderEmail ?? undefined ,
sent_at: sentAt
});
const pixelUrl = ` ${ baseUrl } /t/ ${ token } .gif` ;
The user_id is generated once during extension installation and persists across sessions. The email_id is a new UUID for each message.
Pixel injection
The content script monitors Gmail compose dialogs and injects tracking pixels when you send messages.
Compose dialog detection
The extension scans for compose dialogs and binds event listeners:
// extension/src/content/gmailCompose.js:161-176
function scanForComposeDialogs () {
const dialogs = document . querySelectorAll ( 'div[role="dialog"]' );
dialogs . forEach (( dialog ) => {
if ( dialog instanceof HTMLElement && dialog . dataset . emailTrackerBound !== "1" ) {
dialog . dataset . emailTrackerBound = "1" ;
bindComposeDialog ( dialog );
}
injectTrackingPixelIfNeeded ( dialog ). catch (( error ) => {
if ( ! isContextInvalidatedError ( error )) {
console . warn ( "Email tracker inject failed:" , error );
}
});
});
}
Send intent detection
The extension detects send actions through multiple event types:
Mousedown events
Captures clicks on send buttons before Gmail processes them // extension/src/content/gmailCompose.js:188-196
dialog . addEventListener (
"mousedown" ,
( event ) => {
if ( isSendIntentTarget ( event . target )) {
triggerInjection ();
}
},
true
);
Keyboard shortcuts
Detects Ctrl+Enter or Cmd+Enter send shortcuts // extension/src/content/gmailCompose.js:209-223
dialog . addEventListener (
"keydown" ,
( event ) => {
const keyboardEvent = event ;
const isEnter = keyboardEvent . key === "Enter" ;
const hasSendModifier = keyboardEvent . ctrlKey || keyboardEvent . metaKey ;
if ( isEnter && hasSendModifier ) {
triggerInjection ();
}
},
true
);
Recipient changes
Re-injects pixel if recipient changes after initial injection // extension/src/content/gmailCompose.js:225-239
dialog . addEventListener (
"input" ,
( event ) => {
const target = event . target ;
if ( target . closest ( '[aria-label="To"], [name="to"]' )) {
triggerInjection ();
}
},
true
);
Pixel HTML structure
The injected pixel is a 1x1 transparent image with zero opacity:
// extension/src/content/gmailCompose.js:280-298
const img = document . createElement ( "img" );
img . setAttribute ( TRACKER_PIXEL_MARKER , "1" );
img . src = response . pixelUrl ; // e.g., https://your-domain.com/t/abc123.gif
img . width = 1 ;
img . height = 1 ;
img . alt = "" ;
img . style . cssText = "width:1px;height:1px;opacity:0;display:block;border:0;" ;
const compactEmailId = encodeUuidCompact ( response . emailId ) || response . emailId ;
const marker = document . createElement ( "div" );
marker . id = `s ${ compactEmailId } ` ;
marker . setAttribute ( "data-email-tracker-marker" , "1" );
marker . setAttribute ( "data-et" , compactEmailId );
marker . hidden = true ;
marker . textContent = " \u200C " ; // Zero-width non-joiner
body . appendChild ( marker );
body . appendChild ( img );
Open detection
When a recipient opens the email, their email client requests the tracking pixel from your server.
Pixel endpoint
The server handles pixel requests at GET /t/:token.gif:
// server/src/routes/track.ts:93-178
trackRouter . get ( "/t/:token.gif" , ( req , res ) => {
const nowMs = Date . now ();
const openedAtIso = new Date ( nowMs ). toISOString ();
const token = req . params . token ;
try {
const payload = decodeTrackingToken ( token );
const ipAddress = getRequestIp ( req );
const userAgent = req . get ( "user-agent" ) || null ;
const emailId = payload . email_id ;
// Check for sender suppression signal
const pendingSuppression = suppressionMap . get ( emailId );
const wasSuppressedBySignal = Boolean ( pendingSuppression );
if ( pendingSuppression ) {
suppressionMap . delete ( emailId );
}
// Record the open event
const result = recordOpenEvent ({
payload ,
ipAddress ,
userAgent ,
openedAtIso ,
forceSenderSuppressed: wasSuppressedBySignal ,
suppressionReason: wasSuppressedBySignal ? "mark_suppress_next" : null
});
console . info (
`[pixel-hit] email_id= ${ payload . email_id } duplicate= ${ result . isDuplicate ? 1 : 0 } sender_suppressed= ${ result . isSenderSuppressed ? 1 : 0 } counted= ${ ! result . isDuplicate && ! result . isSenderSuppressed ? 1 : 0 } unique_open_count= ${ result . openCount } `
);
} catch ( error ) {
console . error ( "Tracking pixel processing failed:" , error );
}
// Always return transparent GIF (even on error)
res . setHeader ( "Cache-Control" , "no-store, no-cache, must-revalidate, max-age=0" );
res . setHeader ( "Pragma" , "no-cache" );
res . setHeader ( "Expires" , "0" );
res . setHeader ( "Content-Type" , "image/gif" );
res . status ( 200 ). send ( TRANSPARENT_PIXEL_GIF );
});
Transparent pixel
The server returns a 1x1 transparent GIF for all requests:
// server/src/routes/track.ts:5
const TRANSPARENT_PIXEL_GIF = Buffer . from (
"R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==" ,
"base64"
);
The server captures rich metadata from each pixel request:
IP address
User agent
Timestamp
// server/src/routes/track.ts:229-245
function getRequestIp ( req ) : string | null {
const forwardedFor = req . headers [ "x-forwarded-for" ];
if ( typeof forwardedFor === "string" && forwardedFor . length > 0 ) {
const first = forwardedFor . split ( "," )[ 0 ]?. trim ();
return first || null ;
}
return req . ip ?? req . socket ?. remoteAddress ?? null ;
}
End-to-end flow
Here’s the complete lifecycle of a tracked email:
User composes email
Gmail compose dialog is detected by content script
Token generation
Background worker generates user_id, email_id, and tracking token
Pixel injection
Content script injects hidden <img> tag with pixel URL into message body
Email sent
Message is sent through Gmail with embedded tracking pixel
Recipient opens email
Recipient’s email client renders HTML and requests pixel URL
Server records open
Tracking server decodes token, extracts metadata, checks for duplicates and suppression, stores event in database
Dashboard updated
Extension and dashboard APIs reflect new open count
Frequently asked questions
Why use a GIF instead of a PNG?
GIF is the smallest image format for a 1x1 transparent pixel (43 bytes base64-encoded). It’s widely supported and recognized as the standard for tracking pixels.
Can recipients block tracking pixels?
Yes. Email clients may:
Block external images by default (requires user to “Load images”)
Proxy images through their servers (e.g., Gmail Image Proxy)
Strip tracking pixels entirely
Tracking relies on recipients loading images in their email client.
What happens if the token is invalid?
The server catches decoding errors and still returns a transparent GIF with a 200 status. Invalid requests are logged but don’t create database records. // server/src/routes/track.ts:166-169
} catch ( error ) {
console . error ( "Tracking pixel processing failed:" , error );
}
// Still returns 200 + GIF
res . status ( 200 ). send ( TRANSPARENT_PIXEL_GIF );
How does tracking work with Gmail's image proxy?
Gmail proxies images through Google’s servers (googleimageproxy). The tracker detects these requests by User-Agent and IP prefix: // server/src/routes/track.ts:10-11, 247-255
const GOOGLE_PROXY_UA_TOKEN = "googleimageproxy" ;
const GOOGLE_PROXY_IP_PREFIXES = [ "66.249." , "64.233." , "74.125." ];
function isGoogleImageProxyHit ( userAgent , ipAddress ) : boolean {
const ua = String ( userAgent || "" ). toLowerCase ();
if ( ! ua . includes ( GOOGLE_PROXY_UA_TOKEN )) {
return false ;
}
const ip = normalizeIp ( ipAddress );
return GOOGLE_PROXY_IP_PREFIXES . some (( prefix ) => ip . startsWith ( prefix ));
}
The system also measures latency between sender suppression signals and proxy hits for debugging.
What data is stored for each open?
Each open event stores:
email_id, user_id, recipient (from token)
opened_at (timestamp)
ip_address, user_agent (from request)
geo_country, geo_region, geo_city, latitude, longitude (from GeoIP)
device_type (currently always ‘other’)
is_duplicate, is_sender_suppressed, suppression_reason (flags)
See Dashboard analytics for query details.
Sender suppression Learn how identity-based suppression prevents counting sender self-opens
Deduplication Understand how duplicate opens are detected and filtered
Dashboard analytics Explore dashboard APIs and analytics features