All Skills > SDK Setup > Browser SDK
Sentry Browser SDK
Opinionated wizard that scans your project and guides you through complete Sentry setup for browser JavaScript — vanilla JS, jQuery, static sites, WordPress, and any JS project without a framework-specific SDK.
Invoke This Skill When
- User asks to "add Sentry to a website" or set up Sentry for plain JavaScript
- User wants to install or configure the Loader Script
- User has a WordPress, Shopify, Squarespace, or static HTML site
- User wants error monitoring, tracing, session replay, or logging without a framework
- No framework-specific SDK applies
Note: SDK versions and APIs below reflect
≥10.0.0.
Always verify against
docs.sentry.io/platforms/javascript/ before implementing.
Phase 1: Detect
CRITICAL — Check for frameworks first. Framework-specific SDKs provide significantly better coverage and must be recommended before proceeding with
.
Step 1A: Framework Detection (Redirect If Found)
bash
# Check for React
cat package.json 2>/dev/null | grep -E '"react"'
# Check for Next.js
cat package.json 2>/dev/null | grep '"next"'
# Check for Vue
cat package.json 2>/dev/null | grep '"vue"'
# Check for Angular
cat package.json 2>/dev/null | grep '"@angular/core"'
# Check for Svelte / SvelteKit
cat package.json 2>/dev/null | grep -E '"svelte"|"@sveltejs/kit"'
# Check for Remix
cat package.json 2>/dev/null | grep -E '"@remix-run/react"|"@remix-run/node"'
# Check for Nuxt
cat package.json 2>/dev/null | grep '"nuxt"'
# Check for Astro
cat package.json 2>/dev/null | grep '"astro"'
# Check for Ember
cat package.json 2>/dev/null | grep '"ember-source"'
# Check for Node.js server frameworks (wrong SDK entirely)
cat package.json 2>/dev/null | grep -E '"express"|"fastify"|"@nestjs/core"|"koa"'
If a framework is detected, stop and redirect:
Why redirect matters: Framework SDKs add router-aware transactions, error boundaries, component tracking, and often SSR coverage. Using
directly in a React or Next.js app loses all of that.
Only continue with
if
no framework is detected.
Step 1B: Installation Method Detection
bash
# Check if there's a package.json at all (bundler environment)
ls package.json 2>/dev/null
# Check package manager
ls package-lock.json yarn.lock pnpm-lock.yaml bun.lockb 2>/dev/null
# Check build tool
ls vite.config.ts vite.config.js webpack.config.js rollup.config.js esbuild.config.js 2>/dev/null
cat package.json 2>/dev/null | grep -E '"vite"|"webpack"|"rollup"|"esbuild"'
# Check for CMS or static site indicators
ls wp-config.php wp-content/ 2>/dev/null # WordPress
ls _config.yml _config.yaml 2>/dev/null # Jekyll
ls config.toml 2>/dev/null # Hugo
ls .eleventy.js 2>/dev/null # Eleventy
# Check for existing Sentry
cat package.json 2>/dev/null | grep '"@sentry/'
grep -r "sentry-cdn.com\|js.sentry-cdn.com" . --include="*.html" -l 2>/dev/null | head -3
What to determine:
| Question | Impact |
|---|
| exists + bundler? | → Path A: npm install |
| WordPress, Shopify, static HTML, no npm? | → Path B: Loader Script |
| Script tags only, no Loader Script access? | → Path C: CDN bundle |
| Already has ? | Skip install, go straight to feature config |
| Build tool is Vite / webpack / Rollup / esbuild? | Source maps plugin to configure |
Phase 2: Recommend
Present a recommendation based on what you found. Lead with a concrete proposal, don't ask open-ended questions.
Recommended (core coverage):
- ✅ Error Monitoring — always; captures unhandled errors and promise rejections
- ✅ Tracing — recommended for any interactive site; tracks page load and user interactions
- ✅ Session Replay — recommended for user-facing apps; records sessions around errors
Optional (enhanced observability):
- ⚡ User Feedback — capture reports directly from users after errors
- ⚡ Logging — structured logs via ; requires npm or CDN logs bundle (not available via Loader Script)
- ⚡ Profiling — JS Self-Profiling API; beta, Chromium-only, requires
Document-Policy: js-profiling
response header
Feature recommendation logic:
| Feature | Recommend when... |
|---|
| Error Monitoring | Always — non-negotiable baseline |
| Tracing | Always for interactive pages — page load + navigation spans are high-value |
| Session Replay | User-facing app, support flows, or checkout pages |
| User Feedback | Support-focused app; want in-app bug reports with screenshots |
| Logging | Structured log search or log-to-trace correlation needed; npm path only |
| Profiling | Performance-critical, Chromium-only app; Document-Policy: js-profiling
header required |
Installation path recommendation:
| Scenario | Recommended path |
|---|
| Project has + bundler | Path A (npm) — full features, source maps, tree-shaking |
| WordPress, Shopify, Squarespace, static HTML | Path B (Loader Script) — zero build tooling, always up to date |
| Static HTML without Loader Script access | Path C (CDN bundle) — manual tag |
Propose: "I recommend setting up Error Monitoring + Tracing + Session Replay using Path A (npm). Want me to also add Logging or User Feedback?"
Phase 3: Guide
Path A: npm / yarn / pnpm (Recommended — Bundler Projects)
Install
bash
npm install @sentry/browser --save
# or
yarn add @sentry/browser
# or
pnpm add @sentry/browser
Create
Sentry must initialize
before any other code runs. Put
in a dedicated sidecar file:
typescript
import * as Sentry from "@sentry/browser";
Sentry.init({
dsn: import.meta.env.VITE_SENTRY_DSN, // Adjust per build tool (see table below)
environment: import.meta.env.MODE,
release: import.meta.env.VITE_APP_VERSION, // inject at build time
sendDefaultPii: true,
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration({
maskAllText: true,
blockAllMedia: true,
}),
],
// Tracing
tracesSampleRate: 1.0, // lower to 0.1–0.2 in production
tracePropagationTargets: ["localhost", /^https:\/\/yourapi\.io/],
// Session Replay
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
enableLogs: true,
});
DSN environment variable by build tool:
| Build Tool | Variable Name | Access in code |
|---|
| Vite | | import.meta.env.VITE_SENTRY_DSN
|
| Custom webpack | | |
| esbuild | | |
| Rollup | | |
Entry Point Setup
Import
as the
very first import in your entry file:
typescript
// src/main.ts or src/index.ts
import "./instrument"; // ← MUST be first
// ... rest of your app
Source Maps Setup (Strongly Recommended)
Without source maps, stack traces show minified code. Set up the build plugin to upload source maps automatically:
No dedicated browser wizard: There is no
npx @sentry/wizard -i browser
flag. The closest is
npx @sentry/wizard@latest -i sourcemaps
which configures source map upload only for an already-initialized SDK.
typescript
import { defineConfig } from "vite";
import { sentryVitePlugin } from "@sentry/vite-plugin";
export default defineConfig({
build: { sourcemap: "hidden" },
plugins: [
// sentryVitePlugin MUST be last
sentryVitePlugin({
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
],
});
javascript
const { sentryWebpackPlugin } = require("@sentry/webpack-plugin");
module.exports = {
devtool: "hidden-source-map",
plugins: [
sentryWebpackPlugin({
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
],
};
javascript
import { sentryRollupPlugin } from "@sentry/rollup-plugin";
export default {
output: { sourcemap: "hidden" },
plugins: [
sentryRollupPlugin({
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
],
};
javascript
const { sentryEsbuildPlugin } = require("@sentry/esbuild-plugin");
require("esbuild").build({
entryPoints: ["src/index.ts"],
bundle: true,
sourcemap: "hidden",
plugins: [
sentryEsbuildPlugin({
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
],
});
⚠️ esbuild plugin does
not fully support
. Use
instead if code splitting is enabled.
Using (any toolchain / CI):
bash
# After your build step:
npx @sentry/cli sourcemaps inject ./dist
npx @sentry/cli sourcemaps upload ./dist
Add
for auth (never commit):
bash
SENTRY_AUTH_TOKEN=sntrys_...
SENTRY_ORG=my-org-slug
SENTRY_PROJECT=my-project-slug
Path B: Loader Script (WordPress, Static Sites, Shopify, Squarespace)
Best for: Sites without a build system. The Loader Script is a single
tag that lazily loads the full SDK, always stays up to date via Sentry's CDN, and buffers errors before the SDK loads.
Get the Loader Script:
Sentry UI → Settings → Projects → (your project) → SDK Setup → Loader Script
Copy the generated tag and place it as the first script on every page:
html
<!DOCTYPE html>
<html>
<head>
<!-- Configure BEFORE the loader tag -->
<script>
window.sentryOnLoad = function () {
Sentry.init({
// DSN is already configured in the loader URL
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
});
};
</script>
<!-- Loader Script FIRST — before all other scripts -->
<script
src="https://js.sentry-cdn.com/YOUR_PUBLIC_KEY.min.js"
crossorigin="anonymous"
></script>
</head>
...
</html>
Loader loading modes:
| Mode | How | When SDK loads |
|---|
| Lazy (default) | Nothing extra | On first error or manual Sentry call |
| Eager | Add to | After all page scripts finish |
| Manual | Call | Whenever you call it |
Safe to call before SDK loads (buffered):
Sentry.captureException()
html
<script>
window.Sentry && Sentry.onLoad(function () {
Sentry.setUser({ id: "123" });
});
</script>
Set release via global (optional):
html
<script>
window.SENTRY_RELEASE = { id: "my-app@1.0.0" };
</script>
Loader Script limitations:
- ❌ No (logging) — npm path only
- ❌ No framework-specific features (React ErrorBoundary, Vue Router tracking, etc.)
- ❌ Tracing headers only added to fetch calls made after SDK loads
- ❌ Version changes take a few minutes to propagate via CDN cache
- ⚠️ Use (not ) on all other scripts when using the loader
CSP requirements:
script-src: https://browser.sentry-cdn.com https://js.sentry-cdn.com
connect-src: *.sentry.io
Path C: CDN Bundles (Manual Script Tags)
Best for: Pages that can't use the Loader Script but need synchronous loading.
Pick the bundle that matches your feature needs and place it before all other scripts:
Errors only (minimal footprint):
html
<script
src="https://browser.sentry-cdn.com/10.42.0/bundle.min.js"
integrity="sha384-L/HYBH2QCeLyXhcZ0hPTxWMnyMJburPJyVoBmRk4OoilqrOWq5kU4PNTLFYrCYPr"
crossorigin="anonymous"
></script>
Errors + Tracing:
html
<script
src="https://browser.sentry-cdn.com/10.42.0/bundle.tracing.min.js"
integrity="sha384-DIqcfVcfIewrWiNWfVZcGWExO5v673hkkC5ixJnmAprAfJajpUDEAL35QgkOB5gw"
crossorigin="anonymous"
></script>
Errors + Session Replay:
html
<script
src="https://browser.sentry-cdn.com/10.42.0/bundle.replay.min.js"
integrity="sha384-sbojwIJFpv9duIzsI9FRm87g7pB15s4QwJS1m1xMSOdV1CF3pwgrPPEu38Em7M9+"
crossorigin="anonymous"
></script>
Errors + Tracing + Replay (recommended full setup):
html
<script
src="https://browser.sentry-cdn.com/10.42.0/bundle.tracing.replay.min.js"
integrity="sha384-oo2U4zsTxaHSPXJEnXtaQPeS4Z/qbTqoBL9xFgGxvjJHKQjIrB+VRlu97/iXBtzw"
crossorigin="anonymous"
></script>
Errors + Tracing + Replay + User Feedback:
html
<script
src="https://browser.sentry-cdn.com/10.42.0/bundle.tracing.replay.feedback.min.js"
integrity="sha384-SmHU39Qs9cua0KLtq3A6gis1/cqM1nZ6fnGzlvWAPiwhBDO5SmwFQV65BBpJnB3n"
crossorigin="anonymous"
></script>
Full bundle (all features):
html
<script
src="https://browser.sentry-cdn.com/10.42.0/bundle.tracing.replay.feedback.logs.metrics.min.js"
integrity="sha384-gOjSzRxwpXpy0FlT6lg/AVhagqrsUrOWUO7jm6TJwuZ9YVHtYK0MBA2hW2FGrIGl"
crossorigin="anonymous"
></script>
CDN bundle variants summary:
| Bundle | Features | When to use |
|---|
| Errors only | Absolute minimum footprint |
| + Tracing | Performance monitoring |
| + Replay | Session recording |
bundle.tracing.replay.min.js
| + Tracing + Replay | Full observability |
bundle.tracing.replay.feedback.min.js
| + User Feedback | + in-app feedback widget |
bundle.logs.metrics.min.js
| + Logs + Metrics | Structured logs (CDN) |
bundle.tracing.replay.feedback.logs.metrics.min.js
| Everything | Max coverage |
Initialize after the script tag:
html
<script>
Sentry.init({
dsn: "https://YOUR_KEY@o0.ingest.sentry.io/YOUR_PROJECT",
environment: "production",
release: "my-app@1.0.0",
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration({
maskAllText: true,
blockAllMedia: true,
}),
],
tracesSampleRate: 1.0,
tracePropagationTargets: ["localhost", /^https:\/\/yourapi\.io/],
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
});
</script>
CDN CSP requirements:
script-src: https://browser.sentry-cdn.com https://js.sentry-cdn.com
connect-src: *.sentry.io
For Each Agreed Feature
Walk through features one at a time. Load the reference file, follow its steps, verify before moving on:
| Feature | Reference | Load when... |
|---|
| Error Monitoring | ${SKILL_ROOT}/references/error-monitoring.md
| Always (baseline) |
| Tracing | ${SKILL_ROOT}/references/tracing.md
| Page load / API call tracing |
| Session Replay | ${SKILL_ROOT}/references/session-replay.md
| User-facing app |
| Logging | ${SKILL_ROOT}/references/logging.md
| Structured log search; npm or CDN logs bundle (not Loader Script) |
| Profiling | ${SKILL_ROOT}/references/profiling.md
| Performance-critical, Chromium-only |
| User Feedback | ${SKILL_ROOT}/references/user-feedback.md
| Capture user reports after errors |
For each feature:
Read ${SKILL_ROOT}/references/<feature>.md
, follow steps exactly, verify it works.
Configuration Reference
Key Options
| Option | Type | Default | Notes |
|---|
| | — | Required. SDK disabled when empty |
| | | e.g., , |
| | — | e.g., or git SHA — links errors to releases |
| | | Includes IP addresses and request headers |
| | — | 0–1; in dev, in prod |
| | — | Per-transaction sampling; overrides rate |
| | same-origin | Outgoing URLs that receive distributed tracing headers |
| | — | Fraction of all sessions recorded |
| | — | Fraction of error sessions recorded |
| | | Enable API (npm or CDN logs bundle; not Loader Script) |
| | | Stack traces on calls |
| | | Breadcrumbs stored per event |
| | | Verbose SDK output to console |
| | — | Proxy URL to bypass ad blockers |
| | | Drop errors matching these patterns |
| | | Drop errors from scripts at these URLs |
| | | Only capture errors from these script URLs |
| | | Forward events to Spotlight local dev overlay |
Browser-Specific Options
| Option | Type | Default | Notes |
|---|
| | — | Base URL for lazy-loading integrations |
skipBrowserExtensionCheck
| | | Skip check for browser extension context |
Global (CDN / Loader Path)
Set the release version before the SDK loads:
html
<script>
window.SENTRY_RELEASE = { id: "my-app@1.0.0" };
</script>
Verification
Trigger test events to confirm Sentry is receiving data:
npm / CDN path:
html
<!-- Add temporarily to your page -->
<button onclick="throw new Error('Sentry Browser Test Error')">
Test Error
</button>
Performance verification (npm path):
javascript
import * as Sentry from "@sentry/browser";
Sentry.startSpan({ name: "Test Span", op: "test" }, () => {
// your operation
});
Manual capture:
javascript
Sentry.captureException(new Error("Manual test"));
Sentry.captureMessage("Manual test message", "info");
Check the Sentry dashboard:
- Issues → error appears within seconds
- Traces → page load transaction visible
- Replays → session recording visible after page interaction
- Logs → structured log entries if logging enabled (npm or CDN logs bundle)
Set
in
and check the browser console if nothing appears.
Phase 4: Cross-Link
After completing browser setup, check for a companion backend missing Sentry coverage:
bash
ls ../backend ../server ../api ../go ../python 2>/dev/null
cat ../go.mod 2>/dev/null | head -3
cat ../requirements.txt ../pyproject.toml 2>/dev/null | head -3
cat ../Gemfile 2>/dev/null | head -3
cat ../pom.xml 2>/dev/null | grep '<artifactId>' | head -3
cat ../composer.json 2>/dev/null | head -3
If a backend exists without Sentry configured, suggest the matching skill:
Troubleshooting
| Issue | Solution |
|---|
| Events not appearing | Set , check DSN, open browser console for SDK errors |
| Source maps not working | Build in production mode (); verify is set |
| Minified stack traces | Source maps not uploading — check build plugin config; run npx @sentry/wizard@latest -i sourcemaps
|
| CDN bundle not found | Check version number in URL; see browser.sentry-cdn.com for latest |
| SRI integrity error | Hash mismatch — re-copy the full tag including attribute from this skill |
| Loader Script not firing | Verify it's the first on the page; check for CSP errors in console |
| Tracing not working with Loader | Fetch calls before SDK loads won't be traced — wrap early calls in |
| not called | Must define before the loader tag |
| Logging not available | requires npm or a CDN bundle with in its name — not supported via Loader Script |
| Profiling not working | Verify Document-Policy: js-profiling
header on document responses; Chromium-only |
| Ad blockers dropping events | Set and add a server-side relay endpoint |
| Session replay not recording | Confirm is in init; check > 0 |
| Replay CSP errors | Add and to your CSP |
| not matching | Check regex escaping; default is same-origin only |
| Events blocked by browser extension | Add denyUrls: [/chrome-extension:\/\//]
to filter extension errors |
| High event volume | Lower (errors) and from in production |
| Source maps uploaded after deploy | Source maps must be uploaded before errors occur — integrate into CI/CD |
| esbuild splitting conflict | doesn't support — use instead |