--- summary: "Email open tracking in gog (Gmail + Cloudflare Worker)" read_when: - Adding/changing Gmail email open tracking - Deploying the tracking worker (Cloudflare D1) --- # Email tracking Goal: track email opens for `gog gmail send` via a tiny tracking pixel served from a Cloudflare Worker. High-level: - `gog gmail send --track` injects a 1×1 image URL into the HTML body. - The Worker receives the request, stores an “open” row in D1, and returns a transparent pixel. - `gog gmail track opens …` queries the Worker and prints opens. Privacy note: - Tracking is inherently sensitive. Treat this as *instrumentation you opt into per email*. - The Worker stores IP + user-agent and can derive coarse geo (depending on CF headers/config). ## Setup (local) Create per-account tracking config + keys: ```sh gog gmail track setup --worker-url https://gog-email-tracker..workers.dev ``` This writes a local config file containing: - `worker_url` (base URL) - per-account tracking keys are stored in your keychain/keyring (not in the JSON file) Optional: auto-provision + deploy with wrangler: ```sh gog gmail track setup --worker-url https://gog-email-tracker..workers.dev --deploy ``` Flags: - `--worker-name`: default `gog-email-tracker-`. - `--db-name`: default to worker name. - `--worker-dir`: default `internal/tracking/worker`. Re-run `gog gmail track setup` any time to re-print the current `TRACKING_KEY` / `ADMIN_KEY` values (it’s idempotent unless you pass explicit `--tracking-key` / `--admin-key`). ## Deploy (Cloudflare Worker + D1) From repo root: ```sh cd internal/tracking/worker pnpm install ``` Provision secrets (use values printed by `gog gmail track setup`): ```sh pnpm exec wrangler secret put TRACKING_KEY pnpm exec wrangler secret put ADMIN_KEY ``` Create and migrate D1: ```sh pnpm exec wrangler d1 create gog-email-tracker pnpm exec wrangler d1 execute --file schema.sql ``` Update `wrangler.toml` to reference the D1 `database_id`, then deploy: ```sh pnpm exec wrangler deploy ``` ## Send tracked mail Tracked email constraints: - Exactly **one** recipient (`--to`; no cc/bcc). - HTML body required (`--body-html`). Optional per-recipient sends: ```sh gog gmail send \ --to a@example.com,b@example.com \ --subject "Hello" \ --body-html "

Hi!

" \ --track \ --track-split ``` `--track-split` sends separate messages per recipient (no CC/BCC; each message has a unique tracking id). Example: ```sh gog gmail send \ --to recipient@example.com \ --subject "Hello" \ --body-html "

Hi!

" \ --track ``` ## Query opens By tracking id: ```sh gog gmail track opens ``` By recipient: ```sh gog gmail track opens --to recipient@example.com ``` Status: ```sh gog gmail track status ``` ## Troubleshooting - `required: --worker-url`: run `gog gmail track setup --worker-url …` first (or pass `--worker-url` again). - `401`/`403` on `/opens`: admin key mismatch; redeploy secrets and re-run `track setup` if needed. - No opens recorded: - ensure the HTML body contains the injected pixel (view “original” in your mail client). - some clients block images by default; “open” only happens after images load.