Help us shape the future of Go! Take the 2026 Go Developer Survey

tracking

package
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 25, 2026 License: AGPL-3.0 Imports: 8 Imported by: 0

Documentation

Overview

Package tracking mints and verifies the per-message tokens used by the email open/click/unsubscribe endpoints, and rewrites an email's HTML to route links through the click tracker and embed the open pixel + unsubscribe footer. An open or click token names the Outbound message (ADR 0053), whatever surface sent it.

Tokens are signed JWTs (HS256) — we reuse the existing JWT secret rather than hand-rolling a MAC. Link rewriting uses the official x/net/html tokenizer, not regexes, so arbitrary author markup round-trips safely.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsExpired

func IsExpired(err error) bool

IsExpired reports whether err from DecodeConfirm means the link is past its TTL, as opposed to malformed or signed with another key: an expired link can be replaced by a new one, an invalid one is simply not ours.

Types

type ConfirmTarget

type ConfirmTarget struct {
	Destination string
	WorkspaceID int64
	ContactID   int64
}

ConfirmTarget is the payload a double-opt-in confirmation link carries (ADR 0013). Like the opt-out, the confirmation is destination-keyed and not source-scoped: confirming an address makes it mailable across sources, so the link records against the destination directly (no contact-row lookup) and survives the contact being deleted between send and click.

type Tracker

type Tracker struct {
	// contains filtered or unexported fields
}

Tracker mints recipient tokens and builds tracking URLs against baseURL.

func New

func New(secret, baseURL string, verifyWith ...string) *Tracker

New builds a Tracker. baseURL is the public origin (e.g. https://sphericon.localhost); a trailing slash is trimmed.

func (*Tracker) ClickURL

func (t *Tracker) ClickURL(messageID int64, dest string) (string, error)

ClickURL wraps a destination link so a click is recorded before redirecting. The destination travels inside the signed token, never as a bare parameter.

func (*Tracker) ConfirmURL

func (t *Tracker) ConfirmURL(target ConfirmTarget) (string, error)

ConfirmURL is the public double-opt-in link (ADR 0013). Like UnsubscribeURL the GET is safe: it renders the SPA confirmation page, and the confirmation is recorded only when the recipient POSTs back (scanner-safe, deliberate consent).

func (*Tracker) Decode

func (t *Tracker) Decode(token string) (int64, error)

Decode validates an open token and returns the Outbound message id it carries. A click token carries a destination and is refused: each link kind has its own token.

func (*Tracker) DecodeClick

func (t *Tracker) DecodeClick(token string) (messageID int64, destination string, err error)

DecodeClick validates a click token and returns the Outbound message id and the destination it carries. An open token (pixel) has no destination and is refused, as is any destination that is not an absolute http(s) URL.

func (*Tracker) DecodeConfirm

func (t *Tracker) DecodeConfirm(token string) (ConfirmTarget, error)

DecodeConfirm validates a confirmation token and returns its target. It rejects a token whose exp has passed (and requires exp to be present), so an expired link cannot confirm — the endpoint surfaces that as "request a new one".

func (*Tracker) DecodeUnsub

func (t *Tracker) DecodeUnsub(token string) (UnsubTarget, error)

DecodeUnsub validates a scoped-unsubscribe token and returns its target.

func (*Tracker) Instrument

func (t *Tracker) Instrument(body string, messageID int64) (string, error)

Instrument routes a body's http(s) links through the click tracker (mid token) and appends the open pixel, nothing else: a Transactional send that asks for tracking uses it as is. On a tokenizer error it falls back to the original body plus the pixel, so a send is never blocked by odd markup.

func (*Tracker) OnHost

func (t *Tracker) OnHost(host string) *Tracker

OnHost returns a Tracker that signs with the same secret but builds every link on https://<host>, the Tracking domain of one message's Sending domain (ADR 0038).

func (*Tracker) OpenURL

func (t *Tracker) OpenURL(token string) string

OpenURL is the 1x1 pixel URL that records an open.

func (*Tracker) Origin

func (t *Tracker) Origin() string

Origin is the public origin the Tracker builds its links on, without a trailing slash.

func (*Tracker) Rewrite

func (t *Tracker) Rewrite(body string, messageID int64, unsub UnsubTarget, postalAddress string) (string, error)

Rewrite prepares a marketing body for one Outbound message: Instrument, plus the unsubscribe footer (scoped to unsub, carrying the workspace's CAN-SPAM postal address).

func (*Tracker) Token

func (t *Tracker) Token(messageID int64) (string, error)

Token mints a signed token naming an Outbound message (open pixel).

func (*Tracker) UnsubscribeFooter

func (t *Tracker) UnsubscribeFooter(target UnsubTarget, postalAddress string) (string, error)

UnsubscribeFooter is the email's unsubscribe footer, scoped to target. Shared by the broadcast Rewrite and the automation send step (which appends it directly). postalAddress is the sending workspace's physical address (CAN-SPAM); when non-empty it is escaped and appended below the unsubscribe line (its own newlines become <br>). An empty address renders the footer unchanged — the address is a non-gating nudge, not a send-blocker.

func (*Tracker) UnsubscribeURL

func (t *Tracker) UnsubscribeURL(target UnsubTarget) (string, error)

UnsubscribeURL is the public link that records the scoped opt-out in target.

type UnsubTarget

type UnsubTarget struct {
	Source      string
	Destination string
	WorkspaceID int64
	ContactID   int64
	BroadcastID int64
}

UnsubTarget is the self-describing payload an unsubscribe link carries. The opt-out is destination-keyed (ADR 0001), so the link records against the destination directly — no contact-row lookup, and it survives the contact being deleted between send and click. BroadcastID is set only for broadcast sends (for per-broadcast attribution); Source is the sending-source string the opt-out is scoped to ("broadcasts" / "automation:<id>" / "everything").

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL