@squasher-ai/browser in apps that run in the browser: React, Vue, Svelte, or plain JavaScript.
This page is tested with version 0.5.0. For a Next.js app, follow the Next.js SDK
page instead.
What the SDK captures
Install the SDK
VITE_:
.env
Keep the browser integration first-party
Bundle the SDK with your application. Do not load it from a third-party CDN or paste a vendor<script src="https://…"> tag into your pages. A bundled SDK is served with your release, so a
vendor account or CDN change cannot replace code on your site without a deployment.
Use a dedicated ingest-only key for browser code. Never expose a server key, read key, or secret in
HTML.
Send data through your own domain
Ad blockers and privacy tools often block requests to analytics and monitoring domains. Send the SDK’s requests through a route on your own site instead. The browser then talks only to your origin, and your Content-Security-Policy can keepconnect-src 'self'.
createSquasherProxy from @squasher-ai/browser/proxy returns a handler that takes a Request and
returns a Response. It forwards only the SDK’s upload routes for your project and key. It drops
cookies, Authorization, and every other header that the SDK does not send, refuses requests from
other sites, limits the body size, and does not follow redirects.
Pick a neutral route name, such as /api/t. Names like /analytics or /tracking are more likely
to match blocker rules.
src/main.ts
The handler runs in any runtime with the Fetch API: Next.js route handlers, Cloudflare Workers,
Hono, Bun, Deno, and Node.js 18 or later.
Initialize the SDK
Callinit once, when your app starts, before it renders.
src/main.ts
init starts error capture, Web Vitals, and session replay. release is optional: set it to the
same value on every page of one deploy, for example the git commit SHA.
Capture React errors
Wrap your app inSquasherErrorBoundary. When a component throws during render, the boundary sends
the error with the component stack and shows the fallback.
src/main.tsx
init before this code runs. The boundary also takes an onError callback.
Capture errors that you catch
src/cart.ts
setUser adds the user to
every later event. captureMessage("Checkout opened", "info") sends a message instead of an error.
Configure session replay
Session replay records each browser session, so that you can watch what the user did before an error. It is on by default. Replay is private by default. It masks all page text and all typed values, and it shows images, video, audio, SVG, and canvas as empty boxes. Password, payment card, and one-time-code fields are always left out, and the recorded page URL has no query string or fragment. Each recorded session counts toward the replays in your plan.src/main.ts
maskAllText: false. Text in elements with the
squasher-mask class or the data-squasher-mask attribute stays masked. blockSelector replaces
the matching elements with an empty box. To turn replay off, set replay: { enabled: false }. See
Session replay for all options.
Product analytics and consent
Product analytics is coming soon. It is available only on plans that include product analytics. On
other plans, Squasher does not accept product events.
track. The SDK sends
product events only after the visitor gives consent.
Set consent
Theconsent option sets the state at startup. The default is "denied". When your consent banner
gets an answer, call setConsent:
src/consent.ts
The SDK writes nothing to
localStorage before consent is "granted".
Each product event that the SDK sends carries consent: "granted". Squasher rejects product events
that do not carry this marker. If you send product events from your server, set
consent: "granted" on each event, and only for visitors who gave consent. You are responsible for
getting consent from your visitors. The marker records your consent decision.
By default, consent controls only product analytics. Errors, Web Vitals, and session replay do not
wait for consent. To make them wait too, set consentMode: "strict". In strict mode, the SDK sends
errors, Web Vitals, and replays only while consent is "granted", and it stops when consent becomes
"denied".
Send product events
src/checkout.ts
track(name, properties)records a custom event. A name can have up to 200 characters.page(name, properties)records a page view. Both arguments are optional.identify(userId, traits)links this visitor to your user ID. Later events include the user ID. The traits go to the properties of the identify event.
analytics: { autoPageviews: true }. The SDK then records
the first page and each navigation in a single-page app. It records a new page view only when the
path changes.
What the SDK removes
Before the SDK sends a product event, it removes personal data from the page address:- It removes the query string and the fragment (the part after
#). To keep a query parameter, add its name toanalytics.allowedQueryParams. The SDK then sends its value as the propertyquery.<name>, not in the path. These properties count toward the limit of 32 keys. - It replaces path segments that look like IDs with
:id. Examples are UUIDs, long hexadecimal values, numbers with 6 or more digits, email addresses, and long tokens. - It keeps only the host name of the referrer, and only when it is a different site.
- It keeps the
utm_source,utm_medium,utm_campaign,utm_term, andutm_contentvalues. - It keeps the ad click IDs
gclid,fbclid,msclkid,ttclid,li_fat_id, andtwclidas text, for revenue attribution. Squasher does not send them to an ad platform. - An event held while consent is pending (
consentBuffer: "pending") is sent after the grant without any data from the page address except the path: no UTM values, click IDs, referrer, orquery.<name>properties. Its own property keys and text values are checked at every depth of objects and arrays: text with a?or#that starts with?or#(after spaces) or contains:,/, or\is cut at the first?or#. So/checkout?email=…is sent as/checkoutandmailto:[email protected]?body=…asmailto:[email protected]; plain text such aspro?stays as it is. When two keys become equal, the first is kept. A value that refers to itself, or is nested more than 32 levels deep, is left out. If a property graph is unsafe or too large to inspect safely, the SDK leaves out that value and continues sending the event.
Log out and delete data
Callreset() when a user logs out. The SDK makes a new anonymous ID and a new session, and later
events have no user ID.
Call forget() when a visitor asks you to delete their data. The SDK removes the stored IDs and the
session ID, deletes the events that it did not send, and sets consent to "denied".
Send a test error
Add a button that throws, and select it once in your running app:Options
sampling applies to events such as errors and messages, not to Web Vitals or replays. It treats
events at warning level and above as errors, so errorRate applies to them.
Limits
initthrows whenapiKeyorprojectIdis empty, and when you call it a second time. Callclose()before you callinitagain.- The SDK sends each event once. It does not retry when the request fails.
- Stack traces from a minified bundle point at the minified files until you upload source maps for the release. When your bundler injects debug IDs, the SDK reads its debug ID registry and sends the debug ID of each frame’s file, so Squasher finds the map even without a release.
- The SDK sends breadcrumbs, but Squasher does not store them.
Give the setup to a coding agent
Copy this prompt into your coding agent to install the SDK the same way:Next steps
Session replay
Watch what the user did before an error.
Upload source maps
Show the original source of minified frames.
Next.js SDK
Capture server and browser errors in a Next.js app.
Read AI triage
Learn what the triage summary tells you.