Audit every field before adding an event
A tracking event can collect more than the event name. A browser analytics request may also contain the current page path, document title, referrer, campaign parameters and custom properties. A URL such as `/reset-password/[email protected]`, a title like `Account for Alice`, or a property containing an email address can turn an otherwise ordinary page view into a record of personal data. The safest fix is to prevent sensitive values from entering analytics at all, rather than hoping to clean them up later.
WhoVisited's browser tracker sends the page origin and path without the query string or fragment, stores the document title, keeps only the referrer origin, and reads the `utm_source`, `utm_medium` and `utm_campaign` values. Custom properties are also accepted as short strings, numbers, booleans or nulls. The server validates size and shape, but these checks are not a personal-data filter: a valid email address or account number can still fit the schema.
- Review routes for email addresses, account numbers, invitation codes, reset tokens or other values embedded in the path. Query strings are omitted by this tracker, but that does not make sensitive query strings safe for other analytics tools or logs.
- Review page titles for names, email addresses or customer-specific details. The tracker records `document.title` as it exists when the event is created.
- Review every custom event and property at the call site. Form fields, search text, support messages and user IDs are common accidental additions.
- Review campaign links. Keep UTM values descriptive of the campaign, such as `spring_launch`, rather than the recipient or a customer record.
Send the business context, not the submitted value
For a conversion report, the useful question is usually which action succeeded and which plan or flow it belonged to—not what the visitor typed. Use a small allowlist of properties with stable, non-identifying values. For example, report a successful request with a form category and page variant, while leaving the message, email address and user identifier in your application database.
const allowedFormTypes = new Set(["demo", "contact"]);
function trackFormSuccess(formType, variant) {
if (!allowedFormTypes.has(formType)) return;
const safeVariant = variant === "short" ? "short" : "standard";
window.whovisited?.track("form_submitted", {
form_type: formType,
variant: safeVariant
});
}
// Call only after the server confirms success.
trackFormSuccess("demo", currentVariant);Keep the event name and property values intentionally boring: fixed categories and experiment labels are easier to compare than arbitrary text. Do not pass the form object, the current user object, an email, a free-text search query, or a database key. A frontend allowlist helps prevent accidents, but it is not a security boundary; validate the data flow in your own code and treat browser-supplied analytics as untrusted.
Fix sensitive routes and titles at their source
If a private value appears in a pathname or title, leaving it out of custom properties is not enough. Prefer opaque route identifiers that do not encode a person or secret, and use generic page titles such as `Reset password`. If a legacy route exposes sensitive values, avoid loading analytics on that route until the application no longer puts those values in the URL or title. Do not rely on a later client-side rewrite: the tracker can record its initial page view as soon as it runs.
The same review should cover third-party analytics and server access logs. WhoVisited omitting the query string from its event path does not remove it from browser history, reverse-proxy logs, email click tracking or another tag on the page. Google Analytics' policy guidance specifically warns that URLs and page titles can contain PII; OWASP's logging guidance recommends excluding or sanitizing sensitive values. These are useful engineering references, not a substitute for assessing the rules that apply to your business.
Verify the actual request in the browser
- Use a test site and synthetic values. Open DevTools, select Network, and filter for `api/v1/events`.
- Trigger the page view and each custom event. Inspect the request payload fields `url`, `title`, `referrer`, `campaign` and `properties`; confirm no form value, user identifier or secret appears.
- Test routes with realistic shapes but fake data, including a path segment and page title. Check redirects and client-side navigation too.
- Inspect any Google Tag Manager tags, other analytics libraries and server logs separately. One clean WhoVisited request does not prove that other collection paths are clean.
- If sensitive data was sent, stop sending it at the source and review your product's retention/deletion controls and applicable incident process. Do not assume changing the tracker code removes events already received.
WhoVisited lets you add custom events and review their conversion counts, but it does not automatically detect or redact names, emails, form values or customer-specific URL paths. Its event schema limits field formats and sizes; those limits protect payload shape and resource use, not privacy. Build your event taxonomy around the decision you need to make, and collect the least detail that can answer it.
References and practical limits
For implementation details, see the [WhoVisited traffic and conversion guide](https://whovisited.net/guides/traffic-source-conversion-tracking) and [form conversion example](/blog/contact-form-conversion-without-form-data). For broader background, consult Google's [PII guidance for Analytics](https://support.google.com/analytics/answer/6366371) and OWASP's [Logging Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html). Product behavior described here reflects the current WhoVisited tracker and ingestion schema; privacy obligations depend on your context and jurisdiction.