Web (Browser) SDK
The Pionne SDK for the browser. Auto-captures JS errors and unhandled promise rejections, enriches every event with browser context (URL, viewport, locale, User-Agent).
Current version: 0.3.6
Install
Section titled “Install”npm install @pionne/webOr via CDN with a <script> tag:
<script src="https://unpkg.com/@pionne/web@latest/dist/pionne.umd.js"></script>Quickstart
Section titled “Quickstart”Initialise the SDK as early as possible — ideally before your app renders, in main.ts or a <script> at the top of <head>.
import { Pionne } from '@pionne/web';
Pionne.init({ token: 'pio_live_…', release: '1.0.0', environment: 'production', sampleRate: 1.0, scrubPii: true,});Pionne.init(options);Pionne.captureException(error, { tags, contexts });Pionne.captureMessage('Something went wrong', { level: 'warning' });Pionne.setUser({ id: 'user_42' });Pionne.setTags({ feature: 'checkout' });Pionne.setEnabled(false); // kill switchPionne.addBreadcrumb({ category: 'ui', message: 'Click on #buy' });Pionne.wrap(fn); // wrap a callback to capture its throwsAuto-capture
Section titled “Auto-capture”window.onerror— uncaught exceptionswindow.onunhandledrejection— promises rejected without.catch()
Auto-context
Section titled “Auto-context”- User-Agent, viewport (width/height), locale (
navigator.language) - Current URL, referrer
- Release, environment
Auto-breadcrumbs
Section titled “Auto-breadcrumbs”console.log/console.warn/console.errorfetch()— URL with query string stripped
Options
Section titled “Options”| Option | Type | Description |
|---|---|---|
token | string | Pionne token (pio_live_…) |
release | string | App version |
environment | string | production, staging, etc. |
sampleRate | number | 0.0 — 1.0, fraction of events sent |
scrubPii | boolean | Mask emails, phones, IBANs |
beforeSend | (event) => event | null | Filtering hook |
sendGeography | boolean | Opt-in: IP-side geo (city/region/country) attached to every event. Default false. |
geographyEndpoint | string | IP→geo lookup URL. Default https://ipapi.co/json/. |
Geography (opt-in)
Section titled “Geography (opt-in)”Pionne can attach the visitor’s approximate city/region/country to every event — useful to spot a regression localised to one country or ISP. Off by default for privacy.
Pionne.init({ token: 'pio_live_…', sendGeography: true, // ← opt-in});How it works:
- A single HTTP call at startup to
https://ipapi.co/json/(4 s timeout). - The result (city, region, country, ISO country code) is cached and joined to every event under
contexts.geo. - If the lookup fails (offline, adblock, rate-limit), the SDK silently keeps shipping events without geo.
- No GPS coordinates, no persistent tracking — just the visitor’s IP reverse-lookup.
Want your own provider? Pass geographyEndpoint: 'https://geo.yourapi.com/' — any URL returning JSON { city, region, country, country_code } (or country_name) works.
Frameworks
Section titled “Frameworks”import { Pionne, PionneErrorBoundary } from '@pionne/web';import ReactDOM from 'react-dom/client';import App from './App';
Pionne.init({ token: 'pio_live_…' });
ReactDOM.createRoot(document.getElementById('root')!).render( <PionneErrorBoundary fallback={<p>Oops, we crashed.</p>}> <App /> </PionneErrorBoundary>);import { createApp } from 'vue';import { Pionne } from '@pionne/web';import App from './App.vue';
Pionne.init({ token: 'pio_live_…' });
const app = createApp(App);app.config.errorHandler = (err) => Pionne.captureException(err as Error);app.mount('#app');import { Pionne } from '@pionne/web';import App from './App.svelte';
Pionne.init({ token: 'pio_live_…' });
const app = new App({ target: document.getElementById('app')! });
// Svelte has no global hook — use windowwindow.addEventListener('error', (e) => Pionne.captureException(e.error));
export default app;<script src="https://unpkg.com/@pionne/web@latest/dist/pionne.umd.js"></script><script> Pionne.init({ token: 'pio_live_…' });</script>Source maps
Section titled “Source maps”Like in React Native, prod builds are minified. To get readable stacks, upload your source maps:
npx @pionne/web upload-sourcemaps \ --release 1.0.0 \ --dir ./dist \ --token pio_live_…You can also automate via a Vite or Webpack plugin — see the Source maps guide. The concept is universal: only the build tool changes.
Anti-token-theft
Section titled “Anti-token-theft”Bundle ID pinning is mobile only (iOS/Android/RN/Flutter) — it protects against APK/IPA decompilation. On the web, your token lives in an env var bundled by your bundler (VITE_PIONNE_TOKEN, NEXT_PUBLIC_PIONNE_TOKEN…) and is trivially extractable from the shipped JS — bundle pinning can’t help there.
The “Bundle ID” field is hidden in the mobile dashboard for Web projects. To limit abuse:
- Regenerate the token (with a 24 h grace period) if you suspect a leak — see Tokens.
- Per-token rate-limit server-side — see Rate limits.
- Tags to differentiate deployments / environments:
Pionne.init({ token: import.meta.env.VITE_PIONNE_TOKEN, tags: { deployment: 'prod', tenant: window.location.host },});More details: Bundle ID Pinning → Backends without bundle_id.
See also
Section titled “See also”- React Native SDK — for mobile apps
- Node.js SDK — for Node backends
- Ingest API — raw HTTP protocol
- Source maps — stack symbolication