Performance Monitoring
Dino Discover is built around a few performance properties. This page covers what they are, how we measure them, and where to look if a production install feels slow.
The storefront bundle budget
Section titled “The storefront bundle budget”The most visible performance property is the size of the storefront
JavaScript bundle. It’s built against Preact (via the
preact/compat alias) instead of React proper, and gated on every PR
by a CI tripwire.
- Long-term target: ≤12 KB gzipped.
- Current tripwire: ≤18 KB gzipped (transiently raised on 2026-05-22 to land the results-page and lead-capture surfaces). A trim follow-up to bring it back to 12 KB is tracked openly in the repo.
The build fails hard if the bundle exceeds the tripwire — so the
budget can’t silently drift. The tripwire check lives in
scripts/check-storefront-bundle-size.sh and runs at the end of
npm run build.
[SCREENSHOT: The terminal output of npm run build showing the storefront-bundle-size check.]
Lazy boot
Section titled “Lazy boot”The page that hosts the quiz is fast on first paint because Dino Discover injects only a ~1.5 KB inline bootstrap server-side. The full storefront bundle (Preact + the quiz engine + the components) only loads on the first shopper interaction — clicking Start, focusing the embed, or hitting the popup trigger when launchers ship.
So the cost on shoppers who scroll past the quiz without engaging is ~1.5 KB inline, no separate HTTP request.
The bootstrap response is variant-agnostic — variant assignment
happens later, on session start — which means the bootstrap HTML is
immutable and CDN-cacheable for a year (Cache-Control: public, max-age=31536000, immutable).
Off the hot path
Section titled “Off the hot path”The places where speed matters most on a WooCommerce store are the cart and checkout pages. Dino Discover deliberately does not touch either:
- No cart-time filters. The plugin registers no
woocommerce_add_to_cart,woocommerce_cart_calculate_fees, or cart-totals filters. A page with the WooCommerce cart on it but no embedded quiz pays zero Dino-Discover cost. - No checkout-time filters. Same property at checkout.
- Async lead push. When a lead is captured, the push to Klaviyo / Mailchimp / webhook happens on Action Scheduler — off the shopper’s request path entirely.
- Async coverage refresh.
CoverageCalculatorruns on Action Scheduler, not synchronously insidePOST /publish.
The shopper-facing endpoints that do run on the request path
(/bootstrap, /sessions, /recommend) read from immutable
snapshots and cached product expansions, so they don’t run database
joins per request.
Caching layers
Section titled “Caching layers”A few caches sit between the engines and the database:
| Cache | Where | What it caches |
|---|---|---|
| Snapshot read cache | WP object cache | The full snapshot payload by ID, version-keyed. Invalidated on publish. |
| Product expansion cache | WP object cache (transient fallback) | The per-target expansion of “all products this answer touches”, with a 24-hour TTL. |
| Result cache | WP object cache | The most-recent recommendation payload per session, for the GET /sessions/{sid}/results re-read. |
The cache layer lives in includes/Engine/Cache/. A
CacheVersionRegistry keys every cache entry to a per-quiz version so
that publishing a new snapshot invalidates the right entries without a
wipe.
Database load
Section titled “Database load”A typical storefront session does three database reads:
- The bootstrap call reads one snapshot row.
- The session-start call writes one session row.
- The recommend call reads the same snapshot (object-cached) and writes one event row.
No N+1 fan-outs on products. The product expansion cache means a recommendation against a flow that touches 500 products does not run 500 queries — it does one cache read.
When to use Catalogue Coverage’s debouncer
Section titled “When to use Catalogue Coverage’s debouncer”If you have an automated workflow that publishes a quiz many times in quick succession (e.g. a script that bulk-updates upvote weights), the CoverageDebouncer will collapse the recompute into a single job at the end of the burst, rather than running once per publish.
You don’t need to configure this — it’s the default. Just be aware that the Coverage page will catch up after the last publish, not during.
Measuring on your own store
Section titled “Measuring on your own store”There’s no in-product “performance dashboard” page in 0.1.0. To verify the bundle size on a production install:
curl -s 'https://yourshop.example/wp-content/plugins/dino-discover/build/storefront.js' \ | gzip -c | wc -cThat returns the gzipped byte count of the storefront bundle as served.
To verify the bootstrap size:
curl -s 'https://yourshop.example/page-with-quiz/' \ | grep -A 200 'id="dino-discover-bootstrap"'The inline bootstrap appears between
<script id="dino-discover-bootstrap"> tags.
When it’s not us
Section titled “When it’s not us”If a page hosting the quiz feels slow, the usual suspects (in declining order of likelihood) are:
- A heavy theme. The host page’s other render cost dwarfs the ~1.5 KB bootstrap. Profile the theme.
- An aggressive page cache misconfigured. Caching
/wp-json/dino-discover/*will break sessions. Exclude them. - WooCommerce HPOS migration in flight. A site mid-migration can be slow on order writes; Dino Discover doesn’t touch orders, but the same site can have other surfaces that do.
If after those three the bundle still feels heavy, file a bug report with the gzipped size and the page URL.
What’s next
Section titled “What’s next”- Analytics Dashboard — the funnel/conversion side of the same telemetry.
- Architecture — the systems map that the performance properties hang off.
- Embedding the Quiz — the host-page side of the bundle story.
- FAQ — common perf-related questions.