Skip to content

Analytics overview

The signals that make the mascot wince or look confused are the ones a product team wants to see in a dashboard: which buttons people rage-click, which fields fail validation, where they give up on a form, which endpoints fail. The analytics plugin records them and sends them where you choose.

import { createPal } from 'pagepal';
import { analytics } from 'pagepal/analytics';
const ux = analytics({ endpoint: '/api/ux' });
createPal({ watch: 'form#checkout', requests: true, plugins: [ux] });

That’s the whole setup. Batches are POSTed to /api/ux with navigator.sendBeacon, which survives the page closing.

40page views
48%had a rage or dead click
1.9savg. wait per view
10%dismissed the mascot

Frustration hotspots

  1. button#apply-coupon "Apply"/checkout · 0 rage, 10 dead10
  2. button#pay "Pay $##"/checkout · 6 rage, 0 dead6
  3. div.plan-card "Enterprise"/pricing · 0 rage, 5 dead5

Form errors by field

  1. input[name="zip"]patternMismatch10
  2. input[name="email"]typeMismatch4

form#checkout: 20 submitted, 10 abandoned, most often on input[name="zip"]

Failing and slow requests

  1. GET /api/shipping/rates0 errors, 10 slow · worst 4.2s10
  2. POST /api/payments3 errors, 0 slow · worst 0.8s3

Sample data: a made-up week of checkout traffic, run through summarize().

  • Rage and dead clicks, by element: the buttons that don’t work, or don’t look like they work.
  • Form errors by field and reason (patternMismatch on the zip code), submits, and abandonment, with the field people were on when they left.
  • Failing and slow requests, grouped by method and sanitized URL, and time spent waiting per page view.
  • Offline time, and how people feel about the mascot: pokes and dismissals.
  • Yours. There is no pagepal server. Nothing is sent unless you configure an endpoint or a send function.
  • Private by default. No typed values, masked labels, sanitized URLs, no identifiers that link page views, and it switches off for Do Not Track and Global Privacy Control. Details →
  • Plays well with your stack. Send to your own API, or to GA4, PostHog, Segment or Plausible. Delivery →
  • Small. About 3.5 KB gzipped, and only in bundles that import it.

The pal in the corner is pagepal itself.