Skip to content

For Developers

This is the developer entry point for Dino Discover. If you’re implementing a quiz on a client site and need to swap the recommendation engine, override the storefront templates, or hook custom analytics into the lead pipeline — start here.

The plugin is built to be extended without forking. The four engine interfaces, the ~55-route REST API, the roughly thirty named hooks, and the WordPress-native template override pattern are the supported surfaces.

  • Architecture — the high-level systems map: container, engines, repositories, REST controllers, cron jobs.
  • Engine Interfaces — the four PHP contracts (Question, Recommendation, Coverage, Statistics) that let you replace the brain of the plugin without rewiring the surface.
  • REST API Reference — the admin and storefront endpoints, grouped by controller, with capability and rate-limit notes.
  • Hook Reference — every dino_discover_* action and filter, with the file:line where it fires.

A few invariants worth knowing before you start extending:

  • Published-only storefront. Storefront endpoints accept only published snapshots. A custom PHPStan rule (PublishedSnapshotOnlyRule) fails the build if any public route reads draft state. The single exception is the admin draft-preview tab, which is admin-session-gated and nonce-protected.
  • HPOS-compatible. Every order read goes through wc_get_orders(). Another PHPStan rule (NoLegacyOrderTableReadRule) refuses code paths that open the legacy posts table for orders.
  • PHP 8.1 floor. The codebase uses enums, readonly value objects, and native union types. PHPStan is pinned to PHP 8.1 so 8.2+ syntax surfaces as an error locally.
  • Two-tier engine filters. Every engine binding takes a global filter (dino_discover_<name>_engine) — see Engine Interfaces.
  • Filterable defaults. Settings keys are settable through the admin UI, but every default is also reachable through a PHP filter, so you can override from wp-config.php or an mu-plugin.

The plugin uses Composer PSR-4:

"autoload": {
"psr-4": {
"DinoDiscover\\": "includes/"
}
}

Every class in includes/ is available under the DinoDiscover\ namespace. The container (PHP-DI 7) wires the dependencies; if you’re adding a new service that other code depends on, register it through the container, not as a global.

LayerLives inRole
Admin SPAsrc/admin/React (@wordpress/element). Builder, Dashboard, Coverage, Settings.
Storefront bundlesrc/storefront/Preact (preact/compat alias). Quiz, results, lead capture.
REST APIincludes/API/Controllers under dino-discover/v1.
Enginesincludes/Engine/Question, Recommendation, Coverage, Statistics.
Repositoriesincludes/Repository/Database access (one repo per domain).
Cronincludes/Cron/Event flush, rollup, prune, coverage refresh.
Snapshotincludes/Snapshot/Publish, restore, hydrate.
Settingsincludes/Settings/Typed schema + store.
Storefrontincludes/Storefront/Renderer, asset loader, shortcode, templates.
Integrationsincludes/Integrations/Klaviyo, Mailchimp, Webhook.
Privacyincludes/Privacy/GDPR exporter / eraser.
Variantincludes/Variant/A/B variant assignor + linker.
Licenceincludes/Licence/Licence client (forward-wired for 1.0).
Supportincludes/Support/Capability, crypto, hash, cron helpers.
PHPStanincludes/PHPStan/Custom rules (TR-1, HPOS, crypto ownership).
  • Swapping the recommendation engineEngine Interfaces § Recommendation.
  • Integrating with an external CRMHook Reference § dino_discover_lead_captured action and the integrations registry filter.
  • Building a custom analytics pipelineHook Reference § lifecycle actions (note: most lifecycle actions ship in 0.1.0; some are documented for the v1 contract but not yet emitted — watch the relevant do_action site before you depend on it).
  • Overriding a storefront templateEmbedding the Quiz § Templates and styling.

Per the Beta gap list, a few developer-facing surfaces are wired in the design but not yet emitted in 0.1.0:

  • Per-quiz _for_quiz filter variants — the design names them (e.g. dino_discover_recommendation_engine_for_quiz) but no callsite exists in includes/ today; only the site-wide single-arg filters fire.

Most lifecycle actions catalogued in the technical design do fire in 0.1.0: dino_discover_quiz_started, dino_discover_question_answered, dino_discover_quiz_completed, dino_discover_quiz_abandoned, dino_discover_recommendation_clicked, dino_discover_lead_captured, dino_discover_order_attributed, dino_discover_before_results, and dino_discover_after_results — see Hook Reference for callsites. The full inventory lives in includes/ — grep for apply_filters and do_action to confirm anything specific.