Skip to content

Indira-kumar/pixelpulse

Repository files navigation

PixelPulse

An email open tracker built around tracking pixels.
Know if your email was read - and auto-resend if it wasn't.

🏆 Hackathon-winning project · Team of 4


Why we built it

Cold emails, follow-ups, important asks - they all suffer from the same blind spot: you don't know if it was read. Existing tools either cost money or hand your email content to a third party. We wanted a free, self-hostable open tracker that does one thing well.

PixelPulse generates a unique 1×1 transparent tracking pixel for every email you send. When the recipient opens the email, their client loads the pixel - which hits our server and logs the open. If a week passes with no open or reply, PixelPulse can automatically resend the email.

Features

  • 📩 Open tracking - generate a unique tracking pixel per email; see when (and from where) it was opened
  • 🔁 Auto-resend - if an email isn't opened or replied to within a configurable window, resend it
  • 🌍 Geo-IP enrichment - capture approximate location, ISP, and VPN/Tor usage of the reader
  • 🔐 Firebase Auth - multi-user support with isolated tracking data per account
  • 📊 Dashboard - clear status notifications: opened / unopened / resent / replied

The Gmail problem (interesting bit)

Gmail proxies all images through googleimageproxy.com. This means when a Gmail user opens your tracked email, you don't get their IP and User-Agent - you get Google's. The tracking still confirms the email was opened, but geo and device data are useless for Gmail recipients.

We surface this honestly in the dashboard rather than reporting Google's IP as the recipient's. We also explored cookie-based tracking as an alternative, but most browsers block third-party cookies by default.

Tech stack

Tech Purpose
Python + Flask HTTP backend, route handlers, pixel-serving endpoint
Firebase Realtime Database Stores tracking entries, link hits, user data
Firebase Authentication Email/password user accounts
ipwhois API Geo-location and ISP enrichment from IP
Heroku Hosting (Procfile-based deploy)

How a tracked email works

  1. User logs in and creates a new tracking entry with a title (typically the email subject)
  2. PixelPulse generates a unique 1×1 transparent PNG with an embedded tracking ID
  3. User drags this image into their email body (drag-drop, not copy-paste - copy-paste embeds it as base64 and breaks tracking)
  4. When the recipient opens the email, their client loads the pixel from PixelPulse's server
  5. The server logs the request - IP, User-Agent, timestamp - and updates the entry's status
  6. If the entry is still "unopened" after the configured window, the resend job fires

Run locally

Prerequisites

  • Python 3 + pip
  • Git
  • A Firebase project (Realtime Database + Authentication enabled)

Setup

# Clone and enter
git clone https://github.com/Indira-kumar/pixelpulse
cd pixelpulse

# Virtual env
python3 -m venv venv
source venv/bin/activate   # macOS/Linux
# venv\Scripts\activate    # Windows

# Install deps
pip install -r requirements.txt

Firebase config

  1. Create a Firebase project and enable Realtime Database + Authentication (Email/Password).
  2. From Project Settings → Service Accounts, click Generate New Private Key and save the JSON as credentials.json in the project root.
  3. In your Realtime Database rules, paste:
{
  "rules": {
    "MailTrackData": {
      "Users": {
        "$uid": {
          ".read": "auth !== null && auth.uid === $uid",
          ".write": "auth !== null && auth.uid === $uid"
        }
      },
      "LinkHits": { ".read": false, ".write": true }
    }
  }
}
  1. Note your Firebase Web API Key and Database URL from project settings - you'll need them next.

Environment variables

# macOS/Linux
export FLASK_ENV="development"
export FIREBASE_API_KEY="your-firebase-api-key"
export FIREBASE_DB_URL="your-firebase-db-url"
export SECRET_KEY="any-random-string"

Run

flask run

Visit http://localhost:5000.

Timezone

Edit routes.py line 38 to match your timezone (default Asia/Colombo):

TIMEZONE = "Asia/Kolkata"   # or whatever

To list valid options:

import pytz; pytz.all_timezones

Team

Indira Kumar A K @Indira-kumar · LinkedIn
Gayathri Sthanusubramonian @Gayathri2522 · LinkedIn
Keshav Rathinavel @keshavrathinavel · LinkedIn
Anshuman Sahoo @Cyberc0re-code · LinkedIn

Disclaimer

Tracking other people's actions across platforms can be considered a privacy violation. Use this responsibly - for your own outbound communication, with awareness of local laws and the recipient's reasonable expectations.

License

MIT - see LICENSE.

About

Email open tracker built around tracking pixels. Hackathon-winning project.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors