Adding an assistant to a WordPress site
Three ways to add the embed, which one to choose, and the caching and consent issues specific to WordPress.
Vishal ChiniwarCo-founder and CTO2026-05-271,213 words
There are three common ways to add a widget script to WordPress, and the difference between them matters more than it appears, because two of them can silently lose your code.
Option 1: theme footer.php, avoid
Editing footer.php directly works until the theme updates, at which point your change is overwritten. If someone has done this and the widget disappeared after a theme update, this is why. Use a child theme if you must edit template files at all.
Option 2: a header and footer script plugin, usually right
A small plugin whose only job is injecting scripts into the head or footer is the pragmatic choice for most sites. It survives theme updates, it is visible to whoever inherits the site, and it can be removed cleanly.
Option 3: enqueue properly in a child theme functions.php, best for developers
Using wp_enqueue_script with the correct hook is the technically correct approach. It participates in dependency ordering and can be conditionally loaded per template.
add_action('wp_enqueue_scripts', function () {
wp_enqueue_script(
'site-assistant',
'https://example.com/widget.js',
array(),
null,
true // load in footer
);
});The final true is the important argument. It puts the script in the footer rather than the head.
Caching will hide your change
This is the single most common WordPress support issue with any embed. Page caching plugins and CDN layers will serve the old HTML without your script for anywhere from minutes to hours. Before concluding the embed failed:
- Purge the page cache plugin.
- Purge the CDN cache if one is in front.
- Test in a private window, since your logged in view often bypasses cache and shows a different result from what visitors see.
That third point causes real confusion, because the site owner sees the widget and the visitor does not, or the reverse.
Consent plugins and script blocking
Many WordPress sites run a consent management plugin that blocks third party scripts until consent is given. These plugins often categorise unknown scripts as marketing or analytics by default, which means the widget will not load for anyone who has not accepted that category.
This is not a bug, and it may well be the behaviour you want. But decide it deliberately: is a support widget functional or marketing under your own consent model? Then configure the plugin to match, rather than discovering by accident that the widget only loads for some visitors.
Training sources
WordPress sites usually expose a sitemap, either from the core or from an SEO plugin. Exclude tag archives, author archives, date archives and paginated listing pages. These are structural pages with little prose and they add noise without adding answers.
Where to put the snippet without a plugin
The theme footer is the obvious place and the wrong one, because a theme update overwrites it and nobody connects the disappearance to the update.
A child theme survives updates and is the correct answer if one already exists. Creating a child theme purely to hold one script tag is heavier than the problem deserves.
The lightest durable option is a small snippet plugin, or a single function hooked to `wp_footer` in a site specific plugin file. Both survive theme changes, and both keep the script somewhere a developer will look.
What WordPress makes hard for a crawler
Page builders are the main obstacle. Output varies enormously, and some builders wrap readable text in nested markup that extracts poorly, producing passages full of layout fragments rather than prose.
Shortcodes that render dynamic content are invisible if they run client side, and perfectly readable if they render server side. There is no way to tell from the editor which you have, so check the rendered source rather than assuming.
Membership and paywall plugins hide content from anonymous visitors, which means the crawler sees the teaser and not the article. Gated documentation has to be uploaded as files if you want it answerable.
Custom post types index normally and are frequently the cleanest source on a WordPress site, for the same reason CMS collections are on Webflow: they are structured.
Reindexing on a platform that publishes constantly
WordPress sites tend to publish more often than marketing sites on other platforms, which makes staleness a more active concern rather than a theoretical one.
The advantage is that WordPress can emit an event. A publish hook can trigger a reindex, which removes the gap entirely for the pages that matter. This is one of the few places where the platform makes freshness easier rather than harder.
The thing to avoid is reindexing on every save. Drafts and autosaves would trigger it constantly and index content that was never published. Hook the transition to published status, not the save.
Plugins that quietly break the assistant
Three categories cause most of the problems, and all three are things a site already has before the assistant arrives.
Aggressive caching plugins can serve a cached page without the newly added script for hours. The fix is a cache purge after adding the embed, and the symptom is an assistant that appears for you and not for anyone else.
Script optimisation plugins that defer, combine or lazy load JavaScript can delay or break the widget. Excluding the assistant script from optimisation is usually a one line setting and is worth doing before debugging anything else.
Consent management plugins may block the script until a category is accepted, which is often correct behaviour and occasionally means the assistant never loads because it was filed under the wrong category.
A note on multisite
On a multisite network, custom code added at the network level applies everywhere, which is almost never what you want, because each site has different content and needs its own agent.
Add the embed per site with a per site agent. The alternative, one agent trained across every site in the network, produces answers drawn from a sibling site, which is confusing at best and a disclosure problem where the sites belong to different clients.
Checking what actually got indexed
WordPress sites accumulate content in ways nobody fully remembers, and the gap between what you think is indexed and what is indexed is usually larger here than on other platforms.
Start with the sitemap your SEO plugin generates. It already reflects decisions about what is public and canonical, and it will typically include archive pages, author pages, tag pages and attachment pages that you do not want as sources.
Attachment pages are the classic problem. Many installations publish a page per uploaded image, containing almost no text, and indexing several hundred of them fills the index with passages that can never answer anything while competing for retrieval.
Category and tag archives are the second. They are lists of excerpts, so they retrieve well against general questions and answer none of them, which is the worst combination.
Exclude both, index posts and pages selectively, and check the resulting count against what you expected. A source count several times larger than your real page count is the signal that archives got swept in.
Related reading
One click deploy: what actually has to be true first
Embedding a widget takes a minute. Making it worth embedding takes longer. Here is the honest checklist.Vishal Chiniwar2026-06-10Keeping an assistant in sync with a changing site
Retraining cadence is a product decision, not a maintenance chore. Here is how to decide it rather than default to it.Vishal Chiniwar2026-05-20
Questions
Signal
Have a question about how this works?
Access is by waitlist, demo request or public-content pilot. Ask directly and we will answer, including where it will not fit.