Paste your store address on the Emporiqa homepage and about ten seconds later you are looking at the chat widget, in your brand colors, sitting on a screenshot of your own storefront, next to three questions a shopper might ask about your actual products. This post explains how that preview is built, the abuse cases we had to handle before shipping it, and the design rule underneath the whole product: the chatbot answers only from the store's synced data, so it cannot invent a price, a stock level, or a return policy.
The fear that shaped the architecture
When I talk to merchants about AI chat, cost is never the first objection. The first objection is brand safety: "what if it promises a customer a discount that doesn't exist?" It is a fair fear. A language model asked about a return window will produce a confident answer whether or not it knows one.
So the product treats that as the main design constraint, not a footnote. Every answer must trace back to something the store gave us.
The grounding pipeline
Each supported platform (WooCommerce, Magento, PrestaShop, Drupal Commerce, Sylius) has an official marketplace plugin. The plugin pushes catalog and policy data to us over signed webhooks: HMAC on every payload, no API keys stored inside the store. All processing runs on our servers, never inside the merchant's storefront.
When a shopper asks something, retrieval runs over that store's own data only, combining lexical and semantic search. The generation step is constrained to what retrieval returned. Three consequences fall out of that one rule:
- No invented products or prices. The model can only recommend items that came back from the store's own catalog, with the price the catalog carries.
- No invented policies. Shipping and returns answers come from the store's synced pages. A discount code the system never received is a discount code it cannot offer.
- A transparent failure mode. When retrieval returns nothing confident, the chatbot says it doesn't know and offers a handoff. Your team gets the full conversation, the shopper's cart, and the question that stumped it.
How the preview is built in ten seconds
The preview tool compresses the pitch into one interaction: see it on your store before you install anything. The pipeline behind it:
- Screenshot on someone else's infrastructure. We never fetch the URL you paste. A screenshot API (ScreenshotOne) renders the public homepage on its own network and returns a JPEG. That one decision removes the whole server-side request forgery class: a pasted URL can never reach our internal network, because nothing we run ever connects to it.
- A vision model reads the image. It proposes the store's short name, its product category, and three questions shoppers would ask, in the visitor's language, referencing products visible in the screenshot. Weak output is discarded rather than shown: if the three questions don't pass a strict gate (length, language, uniqueness), the section is hidden.
- Brand extraction. The dominant brand color comes out of the screenshot, so the widget preview renders in the store's own palette instead of ours.
- An is-this-a-store gate. The vision model also answers one more question: is this an online shop at all? If the answer is a clear no (a news site, a SaaS landing page, someone's prank), no page is published. We tell the visitor plainly instead.
The preview page says, right under the screenshot, that it was generated from the public homepage and that live replies come from a demo catalog until the store connects. Overclaiming here would poison the exact trust the tool exists to build.
What stress-testing taught us
A public form that spends money on every submit (a screenshot render plus a vision call) attracts three kinds of trouble: bots, pranksters, and your own bugs. The defenses are layered: a honeypot field, a signed time-trap that rejects submissions faster than a human could type, per-IP rate limits that only count submissions that can spend quota, and a CAPTCHA-less challenge on top.
The best bug was ours. The homepage hands your URL to the preview page, which auto-submits as soon as the anti-bot check issues a token. On fast connections that token arrived in under three seconds, which is faster than the time-trap allows a human to be. The system then politely classified our most motivated visitors as robots and swallowed their request. The fix was one line: the auto-submit now waits out the trap window. If you build time-based bot detection, remember that your own automation is also faster than a human.
What it deliberately doesn't do
- No Shopify app. Self-hosted platforms first, on purpose. I spent 15+ years in the Drupal and Symfony world these platforms come from, and they are the half of e-commerce the AI tooling wave mostly skipped. A public webhook API exists for everything else.
- No training on customer data, zero retention on model calls, and chat history is kept for a fixed 90 days. We are an EU company and we publish our subprocessors; we do not claim EU hosting, because that would not be true.
- No answers from model memory. That's the whole point. If it isn't in your synced data, the chatbot would rather hand off than guess.
Try it
Paste your store address on the homepage and see the preview on your own storefront. Nothing is installed or changed, and the page is deleted on request.
Prefer to poke the live behavior first? Try the demo store and ask something hard, like "wireless headphones under $100 for running, and what if they break in a month?". The demo is a stocked electronics store; connected to your store, it answers from your catalog, with $25 of signup credit and no card at signup.