Skip to content

Latest commit

 

History

History
192 lines (148 loc) · 3.37 KB

File metadata and controls

192 lines (148 loc) · 3.37 KB

Pixel Tracker (Vercel) – Product & Implementation Document

1. Overview

Pixel Tracker is a lightweight serverless service that provides a 1×1 invisible tracking pixel. It logs each request (email open / image load) and stores metadata for later analysis.


2. Objectives

  • Provide a simple tracking pixel endpoint
  • Log every request with metadata
  • Run fully on serverless (no backend server)
  • Easy deployment and local development

3. Core Features

3.1 Tracking Endpoint

  • Endpoint: /api/track?id=<id>
  • Returns: 1×1 transparent PNG
  • Logs:
    • ID
    • Timestamp
    • IP Address
    • User-Agent

3.2 Logs API

  • Endpoint: /api/logs
  • Returns last 100 records

3.3 Storage

  • Uses Redis (Upstash recommended)
  • Logs stored as list

4. Architecture

Client (Email/Web) ↓ /api/track ↓ Serverless Function (Vercel) ↓ Redis Storage


5. Local Setup

Step 1: Create App

npx create-next-app@latest pixel-tracker
cd pixel-tracker
npm install @upstash/redis

Step 2: Environment Variables

Create .env.local

UPSTASH_REDIS_REST_URL=your_url
UPSTASH_REDIS_REST_TOKEN=your_token

6. Folder Structure

pixel-tracker/
├── pages/
│   └── api/
│       ├── track.js
│       └── logs.js
├── lib/
│   └── redis.js

7. Implementation

Redis Client

lib/redis.js

import { Redis } from "@upstash/redis";

export const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL,
  token: process.env.UPSTASH_REDIS_REST_TOKEN,
});

Tracking API

pages/api/track.js

import { redis } from "../../lib/redis";

export default async function handler(req, res) {
  const id = req.query.id || "unknown";

  const log = {
    id,
    time: new Date().toISOString(),
    ip: req.headers["x-forwarded-for"] || "unknown",
    userAgent: req.headers["user-agent"] || "unknown",
  };

  try {
    await redis.lpush("logs", JSON.stringify(log));
  } catch (err) {
    console.error(err);
  }

  const pixel = Buffer.from(
    "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=",
    "base64"
  );

  res.setHeader("Content-Type", "image/png");
  res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
  res.status(200).end(pixel);
}

Logs API

pages/api/logs.js

import { redis } from "../../lib/redis";

export default async function handler(req, res) {
  try {
    const logs = await redis.lrange("logs", 0, 100);
    res.status(200).json(logs.map(JSON.parse));
  } catch (err) {
    res.status(500).json({ error: "Failed to fetch logs" });
  }
}

8. Running Locally

npm run dev

Test endpoints:


9. Usage Example

<img src="http://localhost:3000/api/track?id=user123" width="1" height="1" />

10. Deployment

  1. Push code to GitHub
  2. Import into Vercel
  3. Add environment variables
  4. Deploy

11. Limitations

  • Email clients may cache images
  • Apple Mail preloads images
  • GitHub README may cache requests

12. Future Enhancements

  • Dashboard UI
  • Campaign tracking
  • Click tracking
  • Webhooks
  • Analytics charts

13. Success Criteria

  • Pixel returns 200
  • Logs stored correctly
  • Logs API returns data
  • Works locally and after deployment