Keep data out of analytics
Keep private pages, addresses and properties out of what the web SDK records.
The web SDK gives you three ways to keep data out of analytics: sanitizeUrl rewrites or hides
page addresses, beforeSend edits or drops events, and pauseAnalytics() stops recording for a
while. All three apply before anything is queued or stored.
Keep pages out by address
Some addresses carry data that must not reach Voidhash: a health result in /app/results/42, a
customer ID in an admin page, a token in an invitation link. analytics.sanitizeUrl sees each
address before it is recorded and returns the address to record, or null to keep it out:
import { createVoidhashClient } from "@voidhash/web";
const voidhash = createVoidhashClient({
analytics: {
sanitizeUrl: (url) => {
// Pages with health data stay out entirely.
if (url.pathname.startsWith("/app/")) return null;
// Admin and invitation pages are recorded without the ID or token.
url.pathname = url.pathname
.replace(/^\/admin\/customers\/[^/]+/, "/admin/customers/:id")
.replace(/^\/invite\/[^/]+/, "/invite/:token");
return url;
},
},
publishableKey: "vh_pk_...",
});On a page it returns null for:
- No page view, page leave, outbound click or campaign touch is recorded.
- Events you track there carry no address and no title. To record nothing at all, also drop them
in
beforeSend. - Feature flags,
identify()and delivery of other pages' events keep working.
It also runs on the referrer, which can be another site's address. A rewritten address replaces
the real one everywhere, including a campaign's landing path, and the campaign is read from its
query, so change the URL you get rather than build a new one. It may also return a string, read
relative to the page's address. A function that throws keeps the address out and reports a
SANITIZE_URL_FAILED diagnostic.
sanitizeUrl does not cover data you pass yourself. Keep personal data out of track() and
setPersonAttributes(), and out of the titles of pages you keep, or remove it in beforeSend.
In the Next.js App Router, pass function options to VoidhashProvider from a "use client"
module of your own.
Edit or drop events
analytics.beforeSend sees every event before it is queued: page views, page leaves, outbound
clicks, $set, $sign_out and the events you track. Return the event, changed or not, or null
to drop it:
import { createVoidhashClient } from "@voidhash/web";
const voidhash = createVoidhashClient({
analytics: {
beforeSend: (event) => {
if (event.event === "internal_debug") return null;
delete event.properties.coupon_code;
return event;
},
},
publishableKey: "vh_pk_...",
});| Field | Contents |
|---|---|
event | The name, such as $pageview, $set or one you track. |
properties | Your properties and the SDK's $ properties. A $set event carries its traits in $set and $set_once. |
context | url_origin, url_path, page_title, referrer_origin, referrer_path, and screen and viewport size. |
distinctId, eventId, sessionId, timestamp | Read only. |
- Change
propertiesandcontextin place, or return a new event. Other changes are ignored. - Pass a list of functions to run them in order; the first
nulldrops the event. - A function that throws, or returns anything but an event or
null(such as a promise), drops the event and reportsBEFORE_SEND_FAILED. - It runs once per event, when it is recorded. A dropped event never starts or extends a session.
- Change
$properties only on purpose: Voidhash reads them, for example$platform.
identify() sends no event, so beforeSend does not see it. It sends the user ID and the traits
you pass, without the page's address.
Pause recording
pauseAnalytics() stops recording at once, until resumeAnalytics():
voidhash.pauseAnalytics();
voidhash.isAnalyticsPaused(); // true
voidhash.resumeAnalytics();While paused, nothing is recorded: page views, page leaves, outbound clicks, campaigns, events and
person attributes. Unlike withdrawing consent, the pause is not stored, events queued before it are
still sent, and consent, feature flags and identify() are unaffected. Resuming records nothing by
itself; the next navigation records its page view, or call page(). It works before
initialize(), so even the first page view can be skipped.
The SDK records a page view just after the History API call, before your router renders the new
page. To keep a page out with a pause, pause before the navigation that opens it, such as in your
router's navigation hook, and resume after the visitor leaves it. sanitizeUrl has no such timing
and is usually simpler. In React, useAnalytics() returns pauseAnalytics and resumeAnalytics.
Next steps
Something wrong or missing on this page? Tell us by email or on Discord.