Skip to content

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):

EventMetricProperty
web_vital_lcpLargest Contentful Paintvalue_ms
web_vital_inpInteraction to Next Paint (worst interaction)value_ms
web_vital_clsCumulative Layout Shiftvalue (unitless)
web_vital_fcpFirst Contentful Paintvalue_ms
web_vital_ttfbTime to First Bytevalue_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:

js
// 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_error with endpoint, status_code, latency_ms, method
  • a network failure → api_error with status_code: 0 and the error message
  • a response slower than 2000 msslow_api_response with latency_ms

Disable with errors: false.

Engagement

Automatic behavioral signals that reveal friction and content quality:

EventFires whenProperties
scroll_depth_reachedThe visitor passes 25 / 50 / 75 / 100% of a pagedepth, pathname
time_on_pageOn navigation away or pagehideduration_ms, active_ms (active = tab visible)
rage_click≥ 3 clicks within 800 ms on the same elementtarget_tag, target_text, click_count
dead_clickA click that causes no navigation, no DOM change, and lands on a non-interactive elementtarget_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 Periscale distinct_id.
  • Facebook Pixel dedup — if your business uses server-side Conversions API (CAPI) and no fbq pixel is already on the page, the tag loads the Pixel and fires each conversion with eventID equal 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.

© Periscale