diff --git a/apps/dashboard/app/(main)/websites/[id]/_components/constants/settings-constants.ts b/apps/dashboard/app/(main)/websites/[id]/_components/constants/settings-constants.ts index 7ca367bf1..75737e878 100644 --- a/apps/dashboard/app/(main)/websites/[id]/_components/constants/settings-constants.ts +++ b/apps/dashboard/app/(main)/websites/[id]/_components/constants/settings-constants.ts @@ -69,8 +69,13 @@ export const BASIC_TRACKING_OPTIONS: TrackingOptionConfig[] = [ { key: "trackInteractions", title: "Interactions", - description: "Track button clicks and form submissions", - data: ["Element clicked", "Form submissions"], + description: + "See where visitors get stuck: rage clicks, dead clicks, and forms they abandon", + data: [ + "Rage and dead clicks", + "Clicked element labels, never text", + "Form fields touched and submitted", + ], }, ]; diff --git a/apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.test.ts b/apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.test.ts index 2bdac9995..794ed9d99 100644 --- a/apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.test.ts +++ b/apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.test.ts @@ -3,6 +3,7 @@ import { generateAgentPrompt, generateNpmCode, generateScriptTag, + generateVueCode, } from "./code-generators"; import { RECOMMENDED_DEFAULTS } from "./tracking-defaults"; @@ -69,6 +70,53 @@ assert.ok(prompt.includes("## Common issues")); expect(npm).not.toContain("trackSessions"); }); + it("leaves current-runtime interactions to the default and writes an explicit opt-out", () => { + const off = { ...RECOMMENDED_DEFAULTS, trackInteractions: false }; + + expect( + generateScriptTag("example-client-id", RECOMMENDED_DEFAULTS) + ).not.toContain("track-interactions"); + expect(generateScriptTag("example-client-id", off)).toContain( + 'data-track-interactions="false"' + ); + expect(generateNpmCode("example-client-id", off)).toContain( + "trackInteractions={false}" + ); + expect( + generateNpmCode("example-client-id", RECOMMENDED_DEFAULTS) + ).not.toContain("trackInteractions"); + expect( + generateVueCode("example-client-id", RECOMMENDED_DEFAULTS) + ).not.toContain("track-interactions"); + expect(generateVueCode("example-client-id", off)).toContain( + ':track-interactions="false"' + ); + }); + + it.each([ + true, + false, + ])("keeps explicit interactions=%s for immutable pinned bundles", (trackInteractions) => { + const versionedScript = { + filename: "databuddy.v1.js", + sriHash: "sha384-example", + version: 1, + }; + const script = generateScriptTag( + "example-client-id", + { ...RECOMMENDED_DEFAULTS, trackInteractions, samplingRate: 0.5 }, + versionedScript + ); + + expect(script).toContain(`/${versionedScript.filename}"`); + expect(script).toContain(`integrity="${versionedScript.sriHash}"`); + expect(script).toContain(`data-track-interactions="${trackInteractions}"`); + expect(script).toContain('data-track-web-vitals="true"'); + expect(script).toContain('data-sampling-rate="0.5"'); + expect(script).not.toContain("data-enable-batching"); + expect(script).not.toContain("data-track-attributes"); + }); + it("asks for optional install feedback without code or secrets, and only names real options", () => { const prompt = generateAgentPrompt("example-client-id"); diff --git a/apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.ts b/apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.ts index ae3f4fbf4..ab860f210 100644 --- a/apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.ts +++ b/apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.ts @@ -72,7 +72,7 @@ Page views and sessions are automatic. Turn on the rest based on what the codeba | trackWebVitals | Always. Powers the Web Vitals page (LCP, CLS, INP, TTFB). | | trackErrors | Always for apps with client-side JavaScript. Powers the Errors page. | | trackOutgoingLinks | Marketing sites, docs, link-heavy pages. Records clicks that leave the site. | -| trackInteractions | Apps with buttons and forms worth counting without custom events. | +| trackInteractions | On by default (rage clicks, dead clicks, form drop-off). Set it to false only where the site owner does not want click analytics. | | trackAttributes | When you add data-track attributes to elements instead of calling track(). | | trackHashChanges | Single-page apps that route with the URL hash. | | skipPatterns | Admin, internal, or preview routes that should never be recorded, e.g. ["/admin/**"]. | @@ -343,6 +343,10 @@ export function generateScriptTag( const dataAttrs = Object.entries(trackingOptions) .filter(([key, value]) => { + // Pinned bundles can predate the default-on behavior. + if (versionedScript && key === "trackInteractions" && value === true) { + return true; + } const actualDefault = ACTUAL_LIBRARY_DEFAULTS[key as keyof TrackingOptions]; if (value === actualDefault) { diff --git a/apps/dashboard/app/(main)/websites/[id]/_components/utils/tracking-defaults.ts b/apps/dashboard/app/(main)/websites/[id]/_components/utils/tracking-defaults.ts index 97b7b56ab..ce2cee709 100644 --- a/apps/dashboard/app/(main)/websites/[id]/_components/utils/tracking-defaults.ts +++ b/apps/dashboard/app/(main)/websites/[id]/_components/utils/tracking-defaults.ts @@ -7,7 +7,7 @@ export const ACTUAL_LIBRARY_DEFAULTS: TrackingOptions = { trackAttributes: false, trackOutgoingLinks: false, - trackInteractions: false, + trackInteractions: true, trackWebVitals: false, trackErrors: false,