Open source · No dependencies · MIT

A mascot that actually tells users something.

pagepal reacts to what's happening on your page: form errors, slow requests, buttons that do nothing, going offline. The same signals become UX analytics that you own.

npm install pagepal
cheerForm submitted, back online, back after a while
Live on this page

Don't take our word for it. Poke the page.

The pal in the bottom corner is watching this page. Try these and watch it react. Right now it's neutral

A form error

Submit an invalid email. It winces and turns to look at the field.

→ wince, then cheer when it's valid

A slow request

Requests over 150 ms show the pal waiting. Failures make it wince.

→ waiting, wince

A password field

It covers its eyes while you type, and peeks when you show the password.

→ shy

A button that does nothing

Click once and nothing happens: a dead click. Click it four times fast: a rage click.

→ confused, concerned

Losing the connection

Pretend to go offline (or really do, in DevTools). It's sad until you're back.

→ sad, then cheer

And a lot more

Scroll fast to make it dizzy. Leave it alone for 30 seconds and it dozes off. Poke it, drag it anywhere, or hover and press ✕.

→ dizzy, dozing, wink

Twelve moods

Every reaction means something

When several things happen at once, the most important one wins. A form error while offline shows a wince, then goes back to sad.

  • cheerForm submitted, back online, back after a while
  • winkPoked, text copied, all required fields valid
  • winceValidation error, failed request
  • dizzyScrolling fast
  • concernedRage clicks
  • confusedDead click: nothing happened
  • sadOffline
  • shyPassword field focused
  • waitingRequests in flight
  • dozingUser idle
  • sleepyDark mode
  • neutralNothing going on
Analytics you own

See exactly where users struggle

The signals that move the mascot are the ones you'd want in a dashboard. Add one plugin and pagepal sends them to your endpoint, or to the analytics tool you already use.

  • Rage clicks and dead clicks, by element
  • Form errors by field and reason, and where people abandon
  • Failing and slow endpoints, and time spent waiting
  • Private by default: no typed values, masked labels, respects Do Not Track and GPC
import { createPal } from 'pagepal';
import { analytics } from 'pagepal/analytics';

createPal({
  watch: 'form#checkout',
  requests: true,
  plugins: [analytics({ endpoint: '/api/ux' })],
});
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().

Built for real sites

Welcome on your page, not in the way

Stays out of the way

Steps aside for chat widgets, cookie banners and the field you're typing in. Users can drag it anywhere or dismiss it, and it remembers.

Accessible

The artwork is hidden from screen readers, the dismiss button is a real labelled button, and with reduced motion it changes expression without animating.

Private by default

Nothing is sent unless you configure it. No input values, digits and emails masked, IDs stripped from URLs, consent-aware.

Small and tree-shakable

No dependencies. Build from pagepal/core and pick only the watchers you need. Size budgets are checked in CI.

Isolated

Rendered in a Shadow DOM: your CSS can't break it and its CSS can't leak into your page.

Extensible

Plugins raise their own signals, a debug panel explains every mood, and you can draw your own character.

Characters

Blob, cat, ghost, or your own

Pick a built-in character, draw your own in a few lines of SVG and get every expression for free, or bring your own images for each mood.

Characters & color
Works everywhere

One line in any stack

A web component for plain HTML and every framework, plus first-class React and Vue components. Safe to import during server-side rendering.

<script src="https://unpkg.com/pagepal"></script>
<page-pal watch="form#signup" requests></page-pal>

Give your page a pal

Five minutes to add. Useful from the first form error.