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.
What you get
Section titled “What you get”40page views
48%had a rage or dead click
1.9savg. wait per view
10%dismissed the mascot
Frustration hotspots
button#apply-coupon "Apply"button#pay "Pay $##"div.plan-card "Enterprise"
Form errors by field
input[name="zip"]input[name="email"]
form#checkout: 20 submitted, 10 abandoned, most often on input[name="zip"]
Failing and slow requests
GET /api/shipping/ratesPOST /api/payments
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 (
patternMismatchon 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.
Principles
Section titled “Principles”- Yours. There is no pagepal server. Nothing is sent unless you configure an
endpointor asendfunction. - 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.
EventsEvery event type and its fields.
PrivacyWhat is and isn't recorded, consent, redaction.
Receiving eventsServer examples: Express, Next.js, Cloudflare Workers.
Dashboardssummarize() and building your own reports.
The pal in the corner is pagepal itself.