Putting an AI chatbot on a client site : the decision framework nobody bothers to drawt
Once a month, the same message lands in my inbox. The wording changes, the substance never does: “We’d like to add a little AI chatbot to the site, is that doable?” The client has seen a demo somewhere, pictures a bubble in the bottom right corner answering questions about their products, and reasonably assumes there must be a box to tick somewhere.
The request itself isn’t the problem. It’s perfectly legitimate. The problem is that none of these clients actually want the same thing, and their sites run on anything and everything: Shopify here, WordPress there, Drupal, sometimes a site hand-coded by a contractor who vanished years ago. The question “which plugin?” has no universal answer, because it isn’t the right question.
So here’s the framework I use to decide, whatever the CMS in front of me. It comes down to a single idea: an AI chatbot is two distinct layers that almost everyone collapses into one, and that confusion is exactly what drives the bad decisions.
The Wrong Question (“Which Plugin?”) and the Right One (“Who Owns the Brain?”)
An AI chatbot on a website is really two things that have nothing to do with each other.
First there’s the delivery layer: the visible bubble, the widget, the snippet of code that shows up on the page. This is pure front-end plumbing, and it depends entirely on the CMS. On Shopify you inject it one way, on WordPress another, on a site built from scratch you do whatever you like.
Then there’s the brain layer: the language model that writes the answers, and above all the knowledge base that keeps it from inventing nonsense about your products. This layer is completely indifferent to the CMS. The same brain can serve a Shopify store, a WordPress site, and a custom app without a single line changing.
Nearly every bad integration I’ve seen comes from conflating the two. People pick a “chatbot plugin” thinking they’re choosing a tool, when in reality they’re choosing a package that locks in both a captive delivery layer and a brain they don’t control. So the real question isn’t “which plugin,” it’s: who owns the brain, you or the vendor?
The Control Scale: From Locked-In Turnkey to a Pipeline You Own
Everything sorts onto a single scale, from least to most control. I lay it out exactly like this in front of a client, because it makes the decision obvious.
Level 0, fully turnkey. You hand raw documents to a platform; it chunks, embeds, stores, retrieves, and answers. You touch nothing. This is something like Chaterimo on Shopify: one-click install, you optionally bring your own model API key, and you’re done. Zero effort, zero control. The knowledge base is a black box you feed without ever seeing inside.
Level 1, your own chunks. You supply your content already split into segments, and the platform indexes it. You gain a say over granularity, and nothing else.
Level 2, your own vectors. You compute the numerical representations of your content yourself (which means you choose the model that produces them), and the platform does nothing but store and retrieve.
Level 3, the pipeline you own. Chunking, model, vector store: it’s all yours. The tool wired into the site does nothing but query your index. This is maximum control, and incidentally the only level that lets you reuse the same block of knowledge across ten client sites at once.
The catch is that nearly every turnkey chatbot is locked at Level 0. None of them offer Levels 1 through 3: that territory belongs to the developer pipeline. So the moment a real requirement pushes toward control, you mechanically leave the world of magic plugins behind.
The Delivery Layer, CMS by CMS
Now let’s look at the front-end plumbing, because this is the part clients assume is where everything happens, when it’s actually the easy part.
Shopify
Counterintuitively, Shopify is the cleanest environment of all. There’s a mechanism built for exactly this: the theme app extension paired with an app embed block. In plain terms, you declare a small block that injects your widget into every page without touching the theme, and the merchant can toggle it on or off straight from the editor. The Shopify documentation literally cites chat bubbles as a reference use case.
The advantage over the usual hack (editing the theme by hand): your code survives theme updates and stays reusable from one store to the next. That’s precisely what changes the math when you run an agency.
The one real guardrail: your API key never travels down to the browser. The injected widget calls your backend, and it’s the backend that holds the key and talks to the model. Otherwise any visitor can read your key right out of the page source. Burn that in, because it’s the most common mistake and the most expensive one.
And hiding the key isn’t enough on its own: your backend also has to verify that the request actually came from the legitimate widget, not from a script hammering your endpoint directly. On Shopify, the clean mechanism is the app proxy, which signs requests on Shopify’s side and lets you validate the signature server-side; failing that, a short-lived per-session token does the job. Without it, the rushed developer stands up an open relay API on Render or Supabase, and someone drains the Anthropic bill by spamming the endpoint overnight.
WordPress
This is the “unapologetically plug-and-play” end of the scale, and for once with no embarrassing compromise. The best solution I know is MXchat, because it doesn’t box you in: choice of model, choice of embedding model, and compatibility with external vector stores. It’s rare for a mainstream plugin to leave you that much control.
I actually pushed the experiment further and ran it on a homemade store instead of the default vector service: see MXchat on DuckDB and MotherDuck, where I swap heavy vector infrastructure for plain SQL search. The takeaway here: on WordPress you can sit at Level 0 for convenience while keeping a door open to Level 2 or 3 the day the client outgrows it.
From Scratch and Other CMSs (Drupal, etc.)
This is maximum freedom, and therefore the most demanding. No built-in mechanism, but no constraints either: a lightweight chat widget (a few dozen lines of JavaScript) calls your backend, and that’s it. On Drupal you drop it into a block or a theme region; on a custom site you include it wherever you want. The delivery layer becomes trivial, and all the value shifts to the brain. Which is convenient, because that’s exactly the next subject.
The Brain: Turnkey In-House RAG or a Pipeline You Own
This is where the chatbot’s real quality is decided, and this is where I’ll point you to what I’ve already written in detail, so I don’t rewrite three thousand words about RAG. But here’s the bare minimum to follow along without opening four tabs.
A chatbot that has to answer questions about your products needs RAG (Retrieval Augmented Generation). In one sentence: before letting the model answer, you go fetch the relevant passages from your knowledge base and slip them in front of it, so it cites your data instead of making things up. If you want the full mechanism, I laid it out in RAG Explained Like No One Else Does.
To go fetch those relevant passages, you turn each piece of text into an embedding, that is, into numerical coordinates that let you measure what resembles what. The killer detail: the model that produces those embeddings is almost never chosen on purpose, even though it determines the quality of everything downstream. That’s the whole argument of Your RAG Has an Achilles’ Heel. And this is exactly where turnkey tools betray you: their “bring your own key” option covers the generation model, never the embedding model, which stays imposed internally. You think you’re in control; you control only half of it.
Hence the pivot. If you want your own vector store (Pinecone, say) and your own embedding model, you leave turnkey behind for an orchestration pipeline you own. Concretely, a tool like self-hosted n8n receives the question, embeds it with the model of your choice, queries your index, then passes the retrieved context to the language model. There are even ready-made templates on the n8n side for Shopify and WooCommerce.
A subtlety many people miss: not everyone needs a vector store. If your knowledge is mostly structured (a catalog, spec sheets), retrieval over SQL or BM25 sometimes does better and costs ten times less, as I show in RAG Without a Vector Store. Think “what is the nature of my knowledge” before “which vector store.” And while we’re at it, if you plan to pull public content into that base, first read the trap question everyone gets wrong.
And Sometimes, No RAG at All
The most useful agency reflex I’ve developed is knowing when not to build a RAG. For a site whose knowledge is finite and stable (an auto importer’s catalog, the terms of sale, the shipping FAQ), standing up a Pinecone is pure over-engineering. With today’s context windows, you can often paste all the useful knowledge straight into the prompt and skip retrieval entirely. That’s the shift I describe in From RAG to CAG. Fewer parts, fewer failures, less latency. The question to ask isn’t “how do I build a beautiful RAG,” it’s “do I actually need to go fetch anything at all.”
The Traps I Paid For So You Don’t Have To
A few mistakes I’ve made, or watched others make, all of which cost either time or money.
Stacking two orchestrators. Putting a conversational platform like Botpress out front and n8n behind it to do the same job. Botpress already talks to models natively and knows how to call an external store. Either it does everything, or it’s just a widget and n8n is the brain, but not both elbowing each other. Decide where the brain lives, once.
Sacrificing streaming without realizing it. Routing the model behind a synchronous webhook (the classic case of an n8n wired for a direct response) kills the “answer typing itself out live” effect. The user waits in silence, then the whole thing drops at once. In a chat, that reads as slow even when it’s fast. Getting streaming back behind n8n is possible, but it forces you onto Server-Sent Events or WebSockets, which changes the nature of the plumbing: you’re no longer tweaking a workflow, you’re building a genuine real-time layer. Hence the clean trade-off: either you accept the all-at-once response, or you change your architecture. There’s no painless middle ground.
Trusting your own metrics. A RAG that “works in the demo” and goes off the rails in production is the story of half these projects. Before you ship, measure for real, and be wary of what you’re measuring: your eval metrics are probably wrong.
Underestimating the real economics. “Bring your own key” is almost always more predictable than per-message plans, but you still have to model the usage. I took apart the economics of these offers in The Mirage of Unlimited AI, and showed how to slash the bill in Prompt Caching.
Sovereignty: Who Owns the Knowledge Layer?
At bottom, this whole framework comes back to a question I put to every client, even when they hadn’t seen it coming: who owns the knowledge that runs the bot? At Level 0, it lives with a third party, in a format you can’t see, on infrastructure you don’t control, with all the GDPR implications that carries the moment customer data is involved. At Level 3, it’s yours, on your server, reusable from one site to the next, exportable the day you switch tools.
For a single client with a simple need, Level 0 is perfectly reasonable, and I recommend it without hesitation. For an agency looking to bank a reusable block of knowledge across an entire fleet, it’s the reverse: every hour spent owning the pipeline is an asset, not a cost. It’s the same logic that led me to migrate my entire fleet from PrestaShop to WooCommerce: choosing control over convenience, when the scale justifies it.
My Framework, on a Single Page
Here’s how I actually decide, without agonizing for three days.
| Situation | Delivery layer | Brain | Level |
|---|---|---|---|
| Single client, tight budget, product FAQ | Native Shopify app or WP plugin | Turnkey, in-house RAG | 0 |
| Finite, stable knowledge | Lightweight JS widget (any CMS) | No RAG, everything in context (CAG) | 0 to 1 |
| Client demanding on answer quality | Shopify app embed or MXchat | Chosen model and embedding | 2 |
| Agency, block reusable across the fleet | Custom widget per CMS | Owned pipeline (n8n, your own vector store) | 3 |
| From-scratch site or Drupal | Bespoke JS widget | As needed, from 0 to 3 | variable |
The criterion that overrides all the others: the need for reuse. One site, one need, stay low on the scale and don’t over-build a thing. A fleet, a know-how worth banking, climb and own.
And to close on the horizon, because this framework comes with an expiration date: the chat bubble is a stage, not an endpoint. Tomorrow it won’t be humans querying your pages, but agents, directly. That’s the whole point of WebMCP and of the shift I describe in RAG Is Dead, Long Live the Agent. The chatbot you install today is, at best, the rough draft of the interface your clients will expose to machines tomorrow. Better to build it knowing who owns the brain.