Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Merge site-audit: SEO routes, analytics with consent first in Europe, security page, founder and X account, docs header; the tour opens on the pull request and leads with Code, on the real shell, with Agents and Docs working today | 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; | |
| 3 | ||
| 4 | import { isPublicPath, scrubEvent, scrubPath, scrubUrl } from "./analytics-scrub.ts"; | |
| 5 | ||
| 6 | const ORIGIN = "https://g1t.sh"; | |
| 7 | ||
| 8 | test("the front door is sent as it is", () => { | |
| 9 | for (const path of ["/", "/pricing", "/explore", "/register", "/policies/privacy", "/pricing/"]) { | |
| 10 | assert.equal(isPublicPath(path), true, path); | |
| 11 | assert.equal(scrubPath(path), path); | |
| 12 | } | |
| 13 | }); | |
| 14 | ||
| 15 | test("names in other addresses are replaced, and g1t's own words kept", () => { | |
| 16 | assert.equal(scrubPath("/acme/web/pull/12/files"), "/:name/:name/pull/:n/files"); | |
| 17 | assert.equal(scrubPath("/acme/-/chat/secret-launch"), "/:name/-/chat/:name"); | |
| 18 | assert.equal(scrubPath("/u/sam"), "/u/:name"); | |
| 19 | assert.equal(scrubPath("/invite/abc123"), "/invite/:name"); | |
| 20 | assert.equal(scrubPath("/acme/web/blob/main/src/keys.ts"), "/:name/:name/blob/:name/:name/:name"); | |
| 21 | }); | |
| 22 | ||
| 23 | test("a URL on the site keeps only campaign parameters; another site's is left alone", () => { | |
| 24 | assert.equal(scrubUrl("https://g1t.sh/reset?token=s3cret&utm_source=x", ORIGIN), "https://g1t.sh/reset?utm_source=x"); | |
| 25 | assert.equal(scrubUrl("https://g1t.sh/search?q=private", ORIGIN), "https://g1t.sh/search"); | |
| 26 | assert.equal(scrubUrl("https://g1t.sh/acme/web#L4", ORIGIN), "https://g1t.sh/:name/:name"); | |
| 27 | assert.equal(scrubUrl("https://news.example/acme?x=1", ORIGIN), "https://news.example/acme?x=1"); | |
| 28 | }); | |
| 29 | ||
| 30 | test("a click inside the app goes without its text, link, attributes or title", () => { | |
| 31 | const event = scrubEvent( | |
| 32 | { | |
| 33 | event: "$autocapture", | |
| 34 | properties: { | |
| 35 | $current_url: "https://g1t.sh/acme/secret/issues/3", | |
| 36 | $pathname: "/acme/secret/issues/3", | |
| 37 | $title: "Rotate the prod key · acme/secret · g1t", | |
| 38 | $el_text: "Rotate the prod key", | |
| 39 | $elements_chain: 'a.link:text="Rotate the prod key"href="/acme/secret/issues/3"nth-child="1"attr__class="link"', | |
| 40 | $elements: [{ tag_name: "a", $el_text: "Rotate", href: "/acme/secret", attr__title: "x", nth_child: 1 }], | |
| 41 | $set_once: { $initial_current_url: "https://g1t.sh/acme/secret" }, | |
| 42 | }, | |
| 43 | }, | |
| 44 | "/acme/secret/issues/3", | |
| 45 | ORIGIN, | |
| 46 | ); | |
| 47 | assert.deepEqual(event?.properties, { | |
| 48 | $current_url: "https://g1t.sh/:name/:name/issues/:n", | |
| 49 | $pathname: "/:name/:name/issues/:n", | |
| 50 | $title: "g1t", | |
| 51 | $elements_chain: 'a.link:nth-child="1"', | |
| 52 | $elements: [{ tag_name: "a", nth_child: 1 }], | |
| 53 | $set_once: { $initial_current_url: "https://g1t.sh/:name/:name" }, | |
| 54 | }); | |
| 55 | }); | |
| 56 | ||
| 57 | test("on the front door a click keeps its text", () => { | |
| 58 | const event = scrubEvent( | |
| 59 | { event: "$autocapture", properties: { $el_text: "Start for free", $title: "g1t · Your team", $pathname: "/" } }, | |
| 60 | "/", | |
| 61 | ORIGIN, | |
| 62 | ); | |
| 63 | assert.deepEqual(event?.properties, { $el_text: "Start for free", $title: "g1t · Your team", $pathname: "/" }); | |
| 64 | }); | |
| 65 | ||
| 66 | test("recordings and error reports are never sent, and heatmaps only from the front door", () => { | |
| 67 | assert.equal(scrubEvent({ event: "$snapshot", properties: {} }, "/", ORIGIN), null); | |
| 68 | assert.equal(scrubEvent({ event: "$exception", properties: {} }, "/", ORIGIN), null); | |
| 69 | assert.equal(scrubEvent({ event: "$$heatmap", properties: {} }, "/acme/web", ORIGIN), null); | |
| 70 | const heatmap = scrubEvent({ event: "$$heatmap", properties: { $heatmap_data: { "https://g1t.sh/pricing?ref=mail": [1] } } }, "/pricing", ORIGIN); | |
| 71 | assert.deepEqual(heatmap?.properties, { $heatmap_data: { "https://g1t.sh/pricing": [1] } }); | |
| 72 | }); | |
| 73 | ||
| 74 | test("pages after signing in keep their address but not their text, which can show an email address", () => { | |
| 75 | assert.equal(scrubPath("/confirm-email"), "/confirm-email"); | |
| 76 | assert.equal(scrubPath("/login/two-factor"), "/login/two-factor"); | |
| 77 | const event = scrubEvent({ event: "$autocapture", properties: { $el_text: "Resend to sam@example.com" } }, "/confirm-email", ORIGIN); | |
| 78 | assert.deepEqual(event?.properties, {}); | |
| 79 | }); |
This file's history is long; its oldest lines are credited to the oldest commit read.