Local test harness. The widget is in the bottom-right corner.
Checking server…
Add this to the OpenCart theme footer template:
<script src="https://chat.adexa.co.uk/widget.js?v=7" data-endpoint="https://chat.adexa.co.uk" defer></script>
Add the storefront origin to ALLOWED_ORIGINS in .env so the browser
is permitted to call /api/chat. Bump the ?v= number whenever
widget.js changes, so visitors holding a cached copy pick up the new version.
Adexa operates two different contracts, so the widget asks up front whether the visitor is
buying for a business or as a consumer. That choice decides which terms are quoted
(/terms vs /consumer-terms-and-conditions), whether prices lead with
ex-VAT or inc-VAT, and whether approved trade rates are mentioned at all. Product questions
still work before it is answered; the assistant only insists once the topic reaches terms,
returns, warranty or a price commitment.
If the storefront already knows who the visitor is — a logged-in trade account, for example — skip the question entirely:
AdexaChat.setCustomerType('business'); // or 'consumer'
<button onclick="AdexaChat.ask('Do you have a 1200mm prep table?')">
Ask about this product
</button>
| Endpoint | Purpose |
|---|---|
POST /api/chat | Chat turn, streamed as Server-Sent Events. Body: {message, history, customerType} |
GET /api/health | Model, catalogue size, policy sections, last sync times |
GET /api/search?q=… | Raw catalogue search - checks relevance without spending tokens |
| Command | What it does |
|---|---|
npm run sync | Mirror the product catalogue (~90s, walks the id range) |
npm run sync -- --categories | Rebuild only the category tree, from products already on disk |
npm run sync:content | Re-fetch the 13 policy and information pages |
npm run smoke | Check plumbing, prices and tools without spending tokens |
npm run chat:test | Run canned conversations against the real API and print transcripts |