Automated metrics
Beyond the events you track explicitly, the tag automatically captures four categories of signal. Each is on by default and can be turned off via Configuration.
Web vitals (performance)
Real-user Core Web Vitals, captured with the browser's PerformanceObserver and sent on pagehide (or when the tab is hidden):
| Event | Metric | Property |
|---|---|---|
web_vital_lcp | Largest Contentful Paint | value_ms |
web_vital_inp | Interaction to Next Paint (worst interaction) | value_ms |
web_vital_cls | Cumulative Layout Shift | value (unitless) |
web_vital_fcp | First Contentful Paint | value_ms |
web_vital_ttfb | Time to First Byte | value_ms |
Disable with webVitals: false.
Errors & API monitoring
Two kinds of automatic error capture.
JavaScript exceptions
Unhandled errors and rejected promises fire $exception with the message, source file/line, and a truncated stack:
// captured automatically — fires window.periscale.track("$exception", { … })Image load errors are ignored (too noisy). Stack traces are capped at 2000 characters; messages at 500.
API errors & slow responses
The tag patches window.fetch and watches calls to your proxy/backend paths (/api/proxy/ and /api/v1/business/website/). For each watched request:
- a non-2xx response →
api_errorwithendpoint,status_code,latency_ms,method - a network failure →
api_errorwithstatus_code: 0and the error message - a response slower than 2000 ms →
slow_api_responsewithlatency_ms
Disable with errors: false.
Engagement
Automatic behavioral signals that reveal friction and content quality:
| Event | Fires when | Properties |
|---|---|---|
scroll_depth_reached | The visitor passes 25 / 50 / 75 / 100% of a page | depth, pathname |
time_on_page | On navigation away or pagehide | duration_ms, active_ms (active = tab visible) |
rage_click | ≥ 3 clicks within 800 ms on the same element | target_tag, target_text, click_count |
dead_click | A click that causes no navigation, no DOM change, and lands on a non-interactive element | target_tag, target_text |
Scroll depth and time-on-page are SPA-aware: the tag hooks history.pushState / replaceState so virtual navigations (e.g. Next.js route changes) reset and flush correctly without a full page load.
Disable with engagement: false.
Conversion pixels & vendor tags
Some ad/analytics vendors can only fire in the browser. When your business configures them, the tag injects them automatically (toggle with vendorTags: false):
- Microsoft Clarity — has no server-side ingestion API, so the JS tag is injected with your project id and
clarity('identify', …)is called so Clarity sessions correlate with the Periscaledistinct_id. - Facebook Pixel dedup — if your business uses server-side Conversions API (CAPI) and no
fbqpixel is already on the page, the tag loads the Pixel and fires each conversion witheventIDequal to the SDK event's UUID — the same id the worker sends to CAPI — so Meta deduplicates the browser and server events instead of double-counting.
If a fbq pixel is already present on the page, the tag leaves it alone and relies on the server-side CAPI path only.