← back to Trademarks Copyright
src/app/api/drops/pixel/[id]/route.ts
40 lines
import { NextRequest } from "next/server";
import { query } from "@/lib/db";
/**
* 1×1 transparent GIF tracking pixel.
* GET /api/drops/pixel/<deliveryId> — marks the delivery as opened.
* Embedded in drop HTML as <img src=".../pixel/123"> at the bottom.
*/
// 43-byte transparent GIF (1×1).
const PIXEL = Uint8Array.from([
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00,
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x00,
0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b,
]);
export async function GET(
_req: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const deliveryId = Number(id);
if (Number.isFinite(deliveryId)) {
// Stamp opened_at (only the first time — keep origin IP out of logs for privacy).
await query(
`UPDATE deliveries SET opened_at = NOW() WHERE id = $1 AND opened_at IS NULL`,
[deliveryId]
).catch(() => {});
}
return new Response(PIXEL, {
headers: {
"content-type": "image/gif",
"content-length": String(PIXEL.length),
"cache-control": "no-store, no-cache, must-revalidate",
pragma: "no-cache",
},
});
}