A simple, open-source email view tracker with a Gmail extension and real-time analytics dashboard.
Install • Self-host • Docker • Features • API • License
Pre-built extension bundles for Chrome / Brave / Edge / any Chromium browser are attached to every Release. They target the hosted backend at magio.deepaksilaych.me (auth-gated).
- Download
magio-extension-chrome.zipfrom the latest release and unzip it. - Open
chrome://extensionsand toggle Developer mode on. - Click Load unpacked → select the unzipped folder.
- Visit magio.deepaksilaych.me once and sign in. The auth cookie persists for a week and is reused by the extension.
- Open Gmail. The Magio eye-icon will appear next to Gmail's Send button.
Want to point the extension at your own backend? Build from source with a custom PLASMO_PUBLIC_API_URL — see Self-host below.
- Node.js 20+
- Docker (for PostgreSQL)
- pnpm (for the extension)
git clone https://github.com/deepaksilaych/magio.git
cd magiodocker-compose up -d postgrescd apps/web
cp .env.example .env
npm install
npx prisma db push
npm run devThe dashboard will be available at http://localhost:3000.
cd apps/extension
cp .env.example .env
pnpm install
pnpm devLoad the unpacked extension from apps/extension/build/chrome-mv3-dev in your browser's extension page.
Magio ships with a Docker Compose file that runs the full stack (PostgreSQL + dashboard):
docker-compose up -dThe dashboard will be available at http://localhost:3000.
- Overview — KPI cards, bar chart with 24h/7d/30d toggle, recent sessions table
- Emails — Searchable, sortable email list with per-email detail panel
- Email Detail — View count, unique IPs, hourly distribution chart, tabular view log with browser/OS/device detection
- Auto-refresh — Dashboard updates every 10 seconds
- Dark theme — Umami-inspired dark UI built with shadcn/ui
- Compose toolbar toggle — "Tracking on/off" button injected next to Gmail's Send button
- Auto-track on send — Tracking pixel embedded automatically when enabled
- Email view sidebar — Streak-style panel showing view count, unique IPs, and recent views when opening sent emails
- Popup — Global toggle for auto-tracking
- Persistent settings — Toggle state saved to localStorage
- Tracking pixel — 1x1 transparent GIF with no-cache headers
- Sender filtering — Sender's own views are excluded by IP matching
- Search API — Look up tracking data by email subject
magio/
├── apps/
│ ├── web/ # Next.js 16 — Dashboard + API
│ │ ├── src/
│ │ │ ├── app/ # Routes: /overview, /emails, /api/*
│ │ │ ├── components/ # UI components (shadcn/ui + Recharts)
│ │ │ ├── hooks/ # useDashboard
│ │ │ └── lib/ # Types, DB connector, utils
│ │ ├── prisma/ # Database schema
│ │ └── Dockerfile
│ └── extension/ # Plasmo — Chrome/Brave extension
│ ├── lib/ # API, Gmail DOM, sidebar, storage
│ ├── content.ts # Gmail content script
│ └── popup.tsx # Extension popup
├── docker-compose.yml # PostgreSQL + web app
└── package.json # Root workspace scripts
Tech stack: Next.js, Tailwind CSS, shadcn/ui, Recharts, Prisma, PostgreSQL, Plasmo.
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/emails |
Register a new tracked email |
GET |
/api/emails |
List all tracked emails with views |
GET |
/api/emails/search?subject=... |
Search emails by subject |
GET |
/api/track/[id].gif |
Tracking pixel (logs view, returns 1x1 GIF) |
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
| Variable | Description |
|---|---|
PLASMO_PUBLIC_API_URL |
URL of the tracking API (default: http://localhost:3000) |
- When you click Send in Gmail, the extension calls
POST /api/emailsto register the email. - A 1x1 transparent GIF pointing to
/api/track/[id].gifis embedded in the email body. - When the recipient opens the email, their client loads the image, hitting the tracking endpoint.
- The endpoint logs the view (IP, User-Agent, timestamp). Sender IP is excluded.
- The dashboard and Gmail sidebar display the collected analytics in real time.
For the tracking pixel to work when recipients open emails outside your network, expose the API with a tunnel:
# Cloudflare (recommended — no warning pages)
cloudflared tunnel --url http://localhost:3000
# ngrok
ngrok http 3000Update PLASMO_PUBLIC_API_URL in apps/extension/.env with the tunnel URL, then restart the extension dev server.
MIT — see LICENSE.