← All writing

Template

How to add an AI chatbot to an existing PHP website

Find the one footer template every page includes, paste the script tag before the closing body tag, allow the crawler in robots.txt, crawl your content, and test on staging first. The install is ten minutes. Preparing what the bot answers from takes the afternoon.

An opened wall junction box of old wiring with one clean new wire run into it.

This is the whole job, in the order you should do it, written for whoever maintains the site rather than for whoever built it. Nothing here runs server-side, so none of it touches your PHP.

Step 1: find the file that ends every page

You need the single template that emits </body> on every public page. On most PHP sites it is one of these:

application/views/templates/footer.php     CodeIgniter
resources/views/layouts/app.blade.php      Laravel
wp-content/themes/<your-theme>/footer.php  WordPress
includes/footer.php                        hand-rolled includes

If you are not sure, search the codebase:

grep -rn "</body>" --include="*.php" . | sort | uniq

One or two hits is a healthy site. Fifteen hits means fifteen pages each close their own body tag, and you have a decision to make: paste into all fifteen, or consolidate them into one include first. Consolidating is better and it is a bigger job than this install, so pasting fifteen times is a defensible choice if you write down where they are.

Check for landing pages outside the framework too. A campaign page dropped into the web root two years ago will not include your footer template, and it will be the page you forget.

Step 2: paste the tag

Copy the snippet from your Chatterbox Install page. It carries your public key and looks like this:

<script src="chatterbox.js" data-key="pk_live_8f3a…"></script>
<?php // immediately before </body> ?>
</body>

Put it before </body>, not in <head>. The widget is under 15KB and loads after your page, which is the behavior you want on a mid-range Android phone.

The key in that tag is a public key. It is designed to be readable by anyone who views source, the same way an analytics ID or a Razorpay key ID is. Do not go looking for a way to hide it, and do not put anything that is secret next to it.

Step 3: let the crawler in

The crawler obeys robots.txt. Old sites often carry a blanket disallow from a staging phase that nobody removed, and it will stop the crawl before it starts. Add:

User-agent: ChatterboxBot
Allow: /

Then check what your host does. Some shared-hosting stacks and WAF rules block unfamiliar user agents before PHP is reached, which looks identical to an empty site from the outside.

Step 4: give it something to answer from

Crawling the site is the fast path and it is rarely the whole answer. Two things to plan for:

Pages behind a login are invisible to a crawler. If your rate card or service scope lives inside a customer portal, upload that document instead.

The answers your staff give on the phone every week are usually not published anywhere. Type those in as question-and-answer pairs by hand. Twenty of them will do more for answer quality than another fifty crawled pages, and the content checklist is the pass to make first.

Step 5: test before it faces customers

On staging

Deploy to staging and open a page. Three things to confirm in the browser console:

The script loads with a 200 rather than a 403 from your WAF. No Content Security Policy violation. No layout collision, which on older sites usually means a z-index fight with a sticky header or a cookie banner.

If you run a CSP, the widget's origin needs to be allowed in script-src and connect-src. A site with no CSP header needs nothing.

On production

Clear the page cache after deploying. Varnish, a Cloudflare cache rule or a WordPress cache plugin will keep serving the old HTML otherwise, and you will spend twenty minutes debugging a tag that is already correct.

Then ask it five real questions from your own inbox, including one it should not be able to answer. Watch what it does with that one. It should refuse and ask for a phone number rather than produce a plausible figure, and that behavior is the thing worth checking before customers do it for you.

Test on a phone. Most of your traffic is on one.

Step 6: the parts that are yours to keep doing

Update your privacy policy. Visitors type questions and hand over a phone number, and that goes to a third-party service. Say so, in the same paragraph where you already mention analytics. Your DPDP obligations for that contact data do not move because a widget collected it.

Re-crawl after you change the site. A crawled page is a snapshot, and a stale price is worse than a missing one.

Read the conversations monthly. The refusals are the useful part: each one is a question your website does not answer, ranked by how often customers asked it. That list is a content backlog somebody actually wants.

Check where the leads land. Confirm the notification email reaches a person who acts on it, not a info@ alias nobody opens. A captured lead that nobody calls back is worse than no widget, because the customer thinks they have been in touch.