Skip to content

feat(analytics): add Speed Insights, URL scrubbing, and dose_logged event#87

Open
JWhite212 wants to merge 4 commits into
mainfrom
feat/vercel-speed-insights-and-events
Open

feat(analytics): add Speed Insights, URL scrubbing, and dose_logged event#87
JWhite212 wants to merge 4 commits into
mainfrom
feat/vercel-speed-insights-and-events

Conversation

@JWhite212
Copy link
Copy Markdown
Owner

Summary

  • Add @vercel/speed-insights and inject from src/routes/+layout.ts so Core Web Vitals (LCP / CLS / INP) show up in the Vercel dashboard alongside Web Analytics.
  • Extend the existing Web Analytics injection with a beforeSend that strips query strings from /log URLs — the free-text search input (?q=...) can carry medication names, so it never reaches the recorded URL.
  • Add a server-side track("dose_logged") call on the dashboard quick-log action. Only safe metadata is sent (source, hasNotes, hasSideEffects); no medication id/name, notes content, or side-effect strings. Wrapped in try/catch so a Vercel beacon failure can never break a dose log.

Privacy posture

  • Vercel Analytics is cookieless by default (hashed visitor IDs), GDPR-friendly.
  • /log query strings scrubbed at the source.
  • Medication ID in paths like /medications/[id] is a CUID (not a name) — safe to leave.
  • Server-side events carry only booleans/enums, never user content.

No CSP changes required

Vercel insights scripts are served same-origin via /_vercel/insights/* and /_vercel/speed-insights/*, which the existing script-src 'self' / connect-src 'self' already allow.

Follow-ups (not in this PR)

Same track() pattern can be applied to:

  • medication_created / medication_archived (medications/new, medications/[id])
  • export_pdf / export_csv
  • auth_signup / totp_enrolled
  • push_subscribed
  • inventory_adjusted

Test plan

  • npx vitest run — 363/363 pass
  • npm run check — 0 errors (25 pre-existing warnings)
  • npm run build — succeeds
  • After deploy: enable Web Analytics + Speed Insights in Vercel dashboard
  • After deploy: confirm dose_logged event appears in Vercel Analytics → Events
  • After deploy: confirm /log?q=test is recorded as /log (no query string)

…vent

- Install @vercel/speed-insights and inject from src/routes/+layout.ts
  to surface Core Web Vitals (LCP/CLS/INP) in the Vercel dashboard.
- Extend the existing Web Analytics injection with a beforeSend that
  strips query strings from /log so the free-text search term (?q=)
  never reaches the recorded URL.
- Add a server-side track("dose_logged") call on the dashboard quick-log
  action. Only safe metadata is sent (source, hasNotes, hasSideEffects);
  no medication id/name, notes content, or side-effect strings. Wrapped
  in try/catch so a Vercel beacon failure cannot break a dose log.

No CSP changes required: Vercel insights are served same-origin via
/_vercel/insights/* and /_vercel/speed-insights/*.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Review Change Stack

Warning

Rate limit exceeded

@JWhite212 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 52 minutes and 30 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dc3116bf-57b6-47ca-b649-66f21c2f3ef8

📥 Commits

Reviewing files that changed from the base of the PR and between f0de551 and 414ea4b.

📒 Files selected for processing (1)
  • src/routes/+layout.ts
📝 Walkthrough

Walkthrough

This PR integrates Vercel Analytics and Speed Insights into a medication tracking application. The root layout now configures analytics with URL sanitisation that strips query parameters from /log page events, and injects Speed Insights. The dashboard server page instruments dose-logging events by tracking safe metadata (notes presence, side effects presence, and source) without exposing personally identifiable information.

Changes

Vercel Analytics and Speed Insights

Layer / File(s) Summary
Analytics and Speed Insights setup
src/routes/+layout.ts
Vercel analytics is configured with a beforeSend hook that removes query strings from /log page event URLs to prevent sensitive parameter leakage. Speed Insights is injected via SvelteKit integration.
Dose-logging event tracking
src/routes/(app)/dashboard/+page.server.ts
After successful dose logging, a fire-and-forget track() call emits safe metadata (hasNotes, hasSideEffects, source). Telemetry errors are suppressed so they do not block the user's response.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A rabbit hops through logs with care, 🐰
Tracking doses here and there,
Query strings stripped from sight,
Analytics shining bright!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the three main changes: Speed Insights integration, URL query scrubbing, and dose_logged event tracking.
Description check ✅ Passed The description is comprehensive and directly related to all aspects of the changeset, covering implementation details, privacy considerations, and testing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/routes/+layout.ts (1)

7-17: ⚡ Quick win

Add error handling for URL parsing.

The new URL(event.url) call on line 12 could throw a TypeError if event.url is malformed. Although the library likely provides valid URLs, defensive error handling would prevent the beforeSend hook from breaking if unexpected data is received.

🛡️ Proposed fix to add error handling
 beforeSend(event: BeforeSendEvent) {
   // The /log page accepts a free-text search (`?q=...`) that can contain
   // medication names. Strip the entire query string so it never reaches
   // the recorded URL.
-  if (event.url.includes("/log")) {
+  try {
     const u = new URL(event.url);
-    u.search = "";
-    return { ...event, url: u.toString() };
+    if (u.pathname === "/log" || u.pathname.startsWith("/log/")) {
+      u.search = "";
+      return { ...event, url: u.toString() };
+    }
+  } catch {
+    // If URL parsing fails, return event unchanged
+    return event;
   }
   return event;
 },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/`+layout.ts around lines 7 - 17, Wrap the URL parsing in
beforeSend in a try/catch: when calling new URL(event.url) (inside beforeSend)
catch any TypeError/exception, log a short warning (including the thrown error
and event.url) and return the original event unchanged; only when parsing
succeeds continue to set u.search = "" and return the modified event.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/routes/`(app)/dashboard/+page.server.ts:
- Around line 113-123: The telemetry call is meant to be fire-and-forget but
currently uses await on track("dose_logged") inside the try/catch, which blocks;
change the code to call track("dose_logged", { ... }) without awaiting (e.g.,
call it and optionally append .catch(() => {}) to swallow errors) so the dose
logging path doesn't wait for analytics; update the call site referencing
track("dose_logged") in the same try block and keep the existing non-PII payload
(source, hasNotes, hasSideEffects).

In `@src/routes/`+layout.ts:
- Around line 11-14: The current includes check is too broad; instead parse the
URL (const u = new URL(event.url)) and only clear query params when the pathname
is exactly the /log page (e.g., check u.pathname === '/log' or u.pathname ===
'/log/'), then set u.search = '' and return the modified event; keep references
to event.url, new URL(event.url), u.pathname and u.search when updating the
code.

---

Nitpick comments:
In `@src/routes/`+layout.ts:
- Around line 7-17: Wrap the URL parsing in beforeSend in a try/catch: when
calling new URL(event.url) (inside beforeSend) catch any TypeError/exception,
log a short warning (including the thrown error and event.url) and return the
original event unchanged; only when parsing succeeds continue to set u.search =
"" and return the modified event.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fc7934b3-993f-4aed-bec0-d12cbc5d7881

📥 Commits

Reviewing files that changed from the base of the PR and between 47a0c6a and cb696f7.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • package.json
  • src/routes/(app)/dashboard/+page.server.ts
  • src/routes/+layout.ts

Comment thread src/routes/(app)/dashboard/+page.server.ts
Comment thread src/routes/+layout.ts Outdated
The previous beforeSend used `event.url.includes("/log")`, which is a
substring match — it would also strip query strings from `/auth/login`,
`/auth/logout`, and any future route containing `/log`. Parse the URL
and compare `pathname` exactly to `/log` (with trailing-slash tolerance)
instead.

Wrap the URL parsing in a try/catch so a malformed `event.url` logs a
warning and lets analytics continue with the event unchanged.
Signed-off-by: Jamie White <106563693+JWhite212@users.noreply.github.com>
Copy link
Copy Markdown
Owner Author

@JWhite212 JWhite212 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good

Signed-off-by: Jamie White <106563693+JWhite212@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant