marky

Lightweight bookmarking + plaintext archive
Log | Files | Refs | README | LICENSE

commit 25defcd00c6af26d1c6cb4e23f784cdd1257465b
parent 58fb7a43091a0951bf0dea20950ff6895dd3f5a4
Author: David Eisinger <[email protected]>
Date:   Sat, 11 Oct 2025 17:05:13 -0400

Strip UTM params

Diffstat:
Minternal/api.go | 28++++++++++++++++++++++++++++
1 file changed, 28 insertions(+), 0 deletions(-)

diff --git a/internal/api.go b/internal/api.go @@ -498,6 +498,9 @@ func NewHandlerWithConfig(db *DB, cfg HandlerConfig) (http.Handler, error) { http.Error(w, "invalid url", http.StatusBadRequest) return } + // Strip marketing params (utm*) from the URL before processing + sanitizedURL := stripUTMParams(req.URL) + req.URL = sanitizedURL ctx, cancel := context.WithTimeout(r.Context(), 45*time.Second) defer cancel() isHTML := IsHTMLURL(ctx, req.URL) @@ -1084,6 +1087,31 @@ func toRespWithArchive(ctx context.Context, db *DB, b *Bookmark) bookmarkRespons return br } +// stripUTMParams removes query parameters whose keys start with "utm" (case-insensitive). +func stripUTMParams(raw string) string { + u, err := url.Parse(raw) + if err != nil { + return raw + } + if u.RawQuery == "" { + return raw + } + q := u.Query() + changed := false + for key := range q { + if len(key) >= 3 && strings.HasPrefix(strings.ToLower(key), "utm") { + q.Del(key) + changed = true + } + } + if !changed { + return raw + } + u.RawQuery = q.Encode() + // If nothing left, ensure the URL doesn't end with a bare '?' + return u.String() +} + // RSS structures and writer type rssFeed struct { XMLName xml.Name `xml:"rss"`