How to Configure Email Tracking with Cloudflare Workers and gogcli

You configure email tracking in gogcli by running gog gmail track setup to generate encryption keys and a Cloudflare Worker configuration, then deploying the worker to capture open events via a 1×1 pixel embedded in your emails.

The steipete/gogcli repository provides a complete email-tracking stack that combines a Go CLI with a Cloudflare Worker backend. This guide walks through configuring the tracking infrastructure, deploying the worker, and generating encrypted tracking pixels that record open events in a Cloudflare D1 database.

Setting Up the Tracking Configuration

The first step to configure email tracking with Cloudflare Workers and gogcli is creating a per-account configuration file that stores the worker endpoint and database settings.

Creating the Configuration File

Run the setup command to initialize tracking.json in your gogcli configuration directory (typically $HOME/.config/gog/):

gog gmail track setup \
    --account [email protected] \
    --worker-url https://gog-email-tracker.yourdomain.workers.dev \
    [--worker-name my-tracker] \
    [--no-input]

According to the source in internal/cmd/gmail_track_setup.go, this command performs the following actions:

  1. Validates the account exists in your gogcli configuration
  2. Generates or accepts a 256-bit AES encryption key (tracking_key)
  3. Generates a random admin key for worker administration
  4. Stores both keys in your OS keyring via tracking.SaveSecrets (defined in internal/tracking/config.go)

Understanding the Configuration Structure

The resulting tracking.json contains:

{
  "[email protected]": {
    "worker_url": "https://gog-email-tracker.yourdomain.workers.dev",
    "worker_name": "my-tracker",
    "database_name": "gog-tracking-db",
    "enabled": true
  }
}

The internal/tracking/config.go file handles loading this configuration and hydrating secrets from the system keyring, ensuring sensitive keys never touch disk.

Deploying the Cloudflare Worker

Once configured, you must deploy the tracking worker to Cloudflare's edge network. The worker receives pixel requests, decrypts the payload, and writes open events to a D1 database.

Automatic Deployment with the --deploy Flag

Pass --deploy to the setup command to trigger automatic deployment via the Cloudflare Wrangler CLI:

gog gmail track setup \
    --account [email protected] \
    --worker-url https://gog-email-tracker.yourdomain.workers.dev \
    --deploy

The internal/tracking/deploy.go file implements tracking.DeployWorker, which executes the following sequence:

  1. Creates the D1 database using wrangler d1 create <database_name>
  2. Injects secrets using wrangler secret put TRACKING_KEY and wrangler secret put ADMIN_KEY with the generated AES and admin keys
  3. Patches wrangler.toml in internal/tracking/worker with the worker name and database ID
  4. Deploys the worker using wrangler deploy

If Wrangler is not in your $PATH or you prefer manual control, omit --deploy and the CLI prints the equivalent manual steps (as seen in lines 69-81 of gmail_track_setup.go).

Manual Deployment with Wrangler

If you skipped automatic deployment, run these commands manually:


# 1. Create the D1 database

wrangler d1 create gog-tracking-db

# Note the returned DATABASE_ID

# 2. Configure wrangler.toml

cd internal/tracking/worker

# Edit name, database_name, and database_id

# 3. Upload secrets (get keys from your keyring or the setup output)

wrangler secret put TRACKING_KEY
wrangler secret put ADMIN_KEY

# 4. Deploy

wrangler deploy

The worker code in internal/tracking/worker handles incoming GET requests to /p/<blob>.gif, decrypts the blob using AES-GCM (implemented in internal/tracking/crypto.go), and inserts the event into D1.

Generating and Embedding Tracking Pixels

With the worker deployed, you can generate tracking pixels that report back when recipients open emails.

Creating Pixel URLs in Go

Use the internal/tracking/pixel.go package to generate encrypted URLs:

package main

import (
	"fmt"
	"log"

	"github.com/steipete/gogcli/internal/tracking"
)

func main() {
	// Load configuration and secrets
	cfg, err := tracking.LoadConfig("[email protected]")
	if err != nil {
		log.Fatalf("Failed to load tracking config: %v", err)
	}

	// Generate the pixel URL
	pixelURL, _, err := tracking.GeneratePixelURL(
		cfg,
		"[email protected]",           // recipient email
		"Quarterly Report Discussion",     // subject (hashed for privacy)
	)
	if err != nil {
		log.Fatalf("Failed to generate pixel: %v", err)
	}

	fmt.Println("Tracking URL:", pixelURL)
	// Output: https://gog-email-tracker.yourdomain.workers.dev/p/AbCdEfGhIjKlMnOpQrStUvWxYz123.gif
}

The GeneratePixelURL function (lines 11-34 in pixel.go) encrypts a PixelPayload struct containing the recipient address, a SHA-256 hash of the subject line, and a timestamp using AES-GCM. The resulting blob is base64url-encoded and appended to the worker URL with a .gif extension to ensure email clients render it as an image.

Inserting Pixels into HTML Emails

Convert the URL to an HTML image tag using the helper function:

pixelHTML := tracking.GeneratePixelHTML(pixelURL)
fmt.Println(pixelHTML)

This outputs:

<img src="https://gog-email-tracker.yourdomain.workers.dev/p/AbCdEfGhIjKlMnOpQrStUvWxYz123.gif"
     width="1" height="1"
     style="display:none;width:1px;height:1px;border:0;" alt="" />

The 1×1 pixel is invisible to recipients but triggers a GET request to your Cloudflare Worker when the email client loads images, recording the open event in the D1 database with millisecond precision.

Verifying Your Setup

Confirm the tracking infrastructure is operational using the status command:

gog gmail track status --account [email protected]

This command (implemented in internal/cmd/gmail_track_status.go) reads tracking.json and displays:

  • Worker URL: The endpoint receiving pixel requests
  • Worker Name: The Cloudflare Worker identifier
  • Database ID: The D1 database storing open events
  • Enabled Status: Whether the configuration is active

If the status shows enabled: true and the worker URL responds to HTTP requests, your email tracking with Cloudflare Workers and gogcli is fully configured.

Summary

  • Initialize tracking with gog gmail track setup to generate AES-256 encryption keys and create the tracking.json configuration file stored in internal/tracking/config.go.
  • Deploy automatically using the --deploy flag, which triggers tracking.DeployWorker in internal/tracking/deploy.go to provision a Cloudflare D1 database and upload the worker code with injected secrets.
  • Generate pixels by calling tracking.GeneratePixelURL from internal/tracking/pixel.go, which encrypts recipient data using AES-GCM (defined in internal/tracking/crypto.go) and produces a URL-safe tracking blob.
  • Embed in emails using tracking.GeneratePixelHTML to create invisible 1×1 image tags that report open events to your Cloudflare Worker when recipients view the message.

Frequently Asked Questions

What encryption method does gogcli use for tracking pixels?

gogcli uses AES-256-GCM encryption to secure tracking pixel payloads. The tracking.GenerateKey function in internal/tracking/crypto.go generates a 32-byte (256-bit) random key, while EncryptPixel and DecryptPixel handle the AES-GCM sealed boxes that protect recipient email addresses and subject line hashes stored in the pixel URL.

Can I deploy the Cloudflare Worker manually instead of using the --deploy flag?

Yes, manual deployment is fully supported. If you omit --deploy from the gog gmail track setup command, the CLI outputs the exact Wrangler commands needed to create the D1 database, upload the TRACKING_KEY and ADMIN_KEY secrets, and deploy the worker from internal/tracking/worker. This approach is useful when you need custom wrangler.toml modifications or CI/CD integration.

Where are the encryption keys stored to ensure security?

Encryption keys are stored in the operating system's native keyring, not in the configuration file. The tracking.SaveSecrets function in internal/tracking/config.go uses the zalando/go-keyring library to store the tracking_key and admin_key in macOS Keychain, Windows Credential Manager, or Linux Secret Service. Only non-sensitive metadata like the worker URL and database name resides in tracking.json.

How does the tracking pixel record email opens without exposing recipient data?

The pixel uses one-way hashing and encrypted URL parameters to maintain privacy. When generating a pixel via tracking.GeneratePixelURL in internal/tracking/pixel.go, the subject line is hashed with SHA-256 (not stored in plain text), and the recipient address plus timestamp are encrypted into a URL-safe blob using the AES-256 key. The Cloudflare Worker decrypts this payload only when the image is requested, recording the open event in D1 without ever exposing the original data in server logs or URL history.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →