Connecting ChatGPT to a website means four things move, and none of them is the model itself. The visitor’s question moves to code you control. The passages from your own pages that match that question move alongside it. Any live store data the answer needs moves in from your shop. Then the answer moves back with the page it came from attached. The one hard rule is that your API key must never reach the browser, because anything in client-side JavaScript is readable by anyone who opens developer tools, and the bill for a leaked key is yours.

Everything else is a choice about who writes the middle piece.

What does connecting actually mean?

It means putting something between your visitor and the model, because there is no arrangement in which the two talk directly and you keep your key. That middle piece does the same four jobs regardless of who builds it.

RouteWhat you buildBest forMain limit
A pluginNothing, you configureGetting answering this weekThe vendor’s opinions about retrieval
A no-code connectorA flow in Zapier or MakeTeams already living in those toolsLatency, and per-task pricing at volume
Your own endpointA small server, a few hundred linesOwning the decisionsYou are now maintaining it
A hosted productAn account and a snippetNon-developersYou hold neither the key nor the data

The middle two rows are where most first attempts start and where most of them stall, for the same reason: the first version is genuinely quick, and the distance between a working demo and something you would let a customer touch is much longer than the demo suggests.

Why can the browser not call the API directly?

Because the key would be in the page, and a key in a page is a key in public.

This trips people up because the code looks so simple. A chat completion is one HTTP POST with an Authorization header, the sort of thing fetch does in four lines, and it is tempting to put those four lines on the page and be done. Anyone who opens developer tools then has your credential. People scan for these automatically, and the first you hear about it is the invoice.

There is a second reason that stops the attempt even before the security one. Browsers enforce cross-origin rules, and an API that expects to be called from a server does not hand out permission to be called from arbitrary pages. That is the guardrail working rather than an obstacle to route around.

So the shape is fixed: browser talks to your endpoint, your endpoint talks to the model. Your endpoint is also the only place where you can rate-limit an abusive visitor, log what was asked, and stop a single scraper spending a month’s budget in an afternoon.

How does it learn about your site?

By being handed the relevant part of your site with every question. Nothing else.

A model answers from what it was trained on. That does not include your delivery windows, your current stock or your returns policy, and it may include a version of your site scraped years ago, which is worse than nothing because it is confidently out of date. Making it answer from your content is a two-step job.

First, index. Your pages are split into passages and each passage is converted into a numeric representation, which is what embeddings are for. Store those somewhere you can search.

Second, retrieve at question time. The visitor’s question is converted the same way, the closest passages come back, and those passages are sent to the model with an instruction to answer from them and to say so when they do not contain the answer.

The part people skip is re-indexing. A passage built from a page you have since edited is a quietly wrong answer waiting to happen, and a nightly rebuild means your prices can be fourteen hours stale. Re-reading a page when it changes is the correct behaviour and it is more work than it sounds, which is why plugins that do it well are worth something.

What has to move for a store question?

More than page content, and this is where the integration stops being generic.

What movesFrom whereWhy it matters
The questionThe widget, to your endpointNothing works until you own this hop
Matched passagesYour index of published pagesThe only reason the answer is about you
Order or stock dataYour store, at question timePolicy pages cannot answer “where is mine”
The answer and its sourceBack to the widgetAn answer you cannot check is a rumour

Row three is the one that separates a chatbot that recites your shipping policy from one that tells a customer where their parcel is. On WordPress that means the REST API, and on a shop it usually means the WooCommerce REST API or the equivalent for your platform.

The safe way to wire it is not to hand the model your database. You expose a lookup in your own code, describe it to the model, and let it ask for that lookup by name when a question needs one. That is what function calling does, and the indirection is the security boundary: your code decides whether to run the lookup, which customer it is allowed to run for, and what comes back. A model that can request an order status still cannot change one.

Which of these your site can support without a custom build is on works with, and the wiring itself is in the docs.

What happens when it is slow or down?

Both will happen, and the answer you design for them is more visible to customers than anything about model quality.

Slow first. A single answer is two round trips, not one: find the passages, then generate from them. Cold, that can take several seconds, and a chat window showing nothing for four seconds reads as broken. People close it and do not come back to find out whether it worked.

The fix is to stream. Send the answer as it is produced so the first words appear almost immediately, which turns a four-second wait into a four-second read. While retrieval is still running, say what is happening rather than showing a bare spinner: a line saying it is reading your pages is honest, sets the expectation, and is the difference between waiting and abandoning.

Down second. Model providers have outages, your own host has outages, and a network between them has more. Decide now what the widget says, because the default is a stack trace or a silent failure and both are worse than an honest sentence. Something like not being able to reach the answer service right now, with a link to your contact page, costs nothing and keeps the customer inside your site. Your endpoint should fail to a route, never to an error.

Two smaller things pay for themselves quickly. Put a timeout on the model call, so a request that hangs fails fast into that same route rather than leaving somebody watching a cursor. And cache the answers to identical questions, because the same four questions arrive constantly. A cache turns your most common question into an instant free answer and removes a whole class of variability from the experience.

None of this is exotic engineering. It is the difference between a demo and something a customer meets on a bad day, and it is almost always the work that gets postponed.

When should you not build this yourself?

When the plumbing is not the part of your week you want to spend, which is a legitimate answer rather than an admission.

The first version really is an afternoon. An endpoint, an index over a few dozen pages, a chat window. It will work, and it will feel like the job is nearly done. It is not. What follows is the refusal behaviour, the exclusions for pages that must never be quoted, re-indexing on edit, rate limiting, the widget itself, accessibility, and the slow discovery that your delivery policy contradicts itself across three pages. That is most of a month, and none of it is the interesting part.

Do not build it if you cannot own the key operationally either. Somebody has to notice when spending changes shape, rotate the credential when a laptop is lost, and know which environments hold a copy. A key nobody is responsible for is the most expensive thing on this page.

And if your questions are mostly order status, consider whether a tracking link in the confirmation email removes more of them than any of this. Solve that first and measure what is left; what is left is a smaller and more interesting problem.

Set against that, building it yourself is the right call more often than the market implies. You keep the key, you keep the data, you decide what the thing does when it does not know, and you understand your own failure modes. If you are still deciding what kind of product you want, how to choose one covers the shortlist, and what an AI chatbot for a website actually is covers the category.

What people ask next

How do I connect ChatGPT to my website?

Through something that sits between the two, never directly. The visitor’s question goes to code you control, that code finds the passages from your pages that match it, sends question and passages to the model, and returns the answer. The three ways to get that middle piece are a plugin, a no-code connector like Zapier or Make, or a small endpoint of your own. All three do the same four jobs.

Can I call the OpenAI API from JavaScript in the browser?

Technically you can write the code, and you should not. Anything in client-side JavaScript is readable by anyone who opens developer tools, including your API key, and a key in the open gets found and used by strangers at your expense. The request has to go through a server you control, which also gives you the only place to enforce rate limits and log what happened.

Does ChatGPT know what is on my website?

No, not unless something tells it. A model answers from what it was trained on, which does not include your delivery windows, your stock or your returns policy, and may include an outdated version of your site scraped years ago. Making it answer from your content means indexing your pages and passing the matching passages along with the question, every single time.

How much does it cost to run?

Per token, on both what you send and what comes back, at a published price. Retrieval raises the cost of the input because you are pasting passages into every request, so a long answer with four source passages costs more than a one-line reply. For most small sites this lands in the low tens of euros a month. Your own key means you pay the provider directly, with nothing marked up.

Can the chatbot look up a customer’s order?

Yes, but not by giving the model access to your database. You expose a lookup in your own code, tell the model that the lookup exists, and it asks for it by name when a question needs it. Your code decides whether to run it and what to return. That indirection is the security boundary, and it is the reason a bot can safely read order status without being able to change one.

Should I build this myself or install something?

Build it if the plumbing is the interesting part of your week and you want to own the decisions. Install something if you want it answering by Friday. The honest middle case is the one people miss: a first version takes an afternoon, and the ninety percent that follows is refusal behaviour, exclusions, re-indexing and the widget, which is most of a month.